因项目需要,用c#制作了一个ActiveX插件,功能很简单,控件已实现客户端安装,这些都没问题!我贴的代码是简化了功能的,具体业务没有写,太多。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; namespace ActiveX { [ComVisible(true)] [Guid("C77695C2-7341-4b81-990E-39E91923BB44")] public partial class NontaxActiveX : UserControl, IObjectSafety { public NontaxActiveX() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { if (checkBox1.Checked) { MessageBox.Show(textBox1.Text == "" ? "请输入内容" : textBox1.Text); } else { MessageBox.Show("什么也没有???????"); } } private void textBox1_TextChanged(object sender, EventArgs e) { } #region IObjectSafety成员 private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"; private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}"; private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}"; private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}"; private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001; private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002; private const int S_OK = 0; private const int E_FAIL = unchecked((int)0x80004005); private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true; private bool _fSafeForInitializing = true; public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions) { int Rslt = E_FAIL; string strGUID = riid.ToString("B"); pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; switch (strGUID) { case _IID_IDispatch: case _IID_IDispatchEx: Rslt = S_OK; pdwSupportedOptions = 0; if (_fSafeForScripting == true) pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; break; case _IID_IPersistStorage: case _IID_IPersistStream: case _IID_IPersistPropertyBag: Rslt = S_OK; pdwEnabledOptions = 0; if (_fSafeForInitializing == true) pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA; break; default: Rslt = E_NOINTERFACE; break; } return Rslt; } public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) { int Rslt = E_FAIL; string strGUID = riid.ToString("B"); switch (strGUID) { case _IID_IDispatch: case _IID_IDispatchEx: if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true)) Rslt = S_OK; break; case _IID_IPersistStorage: case _IID_IPersistStream: case _IID_IPersistPropertyBag: if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true)) Rslt = S_OK; break; default: Rslt = E_NOINTERFACE; break; } return Rslt; } #endregion
using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; // 有关程序集的常规信息通过下列属性集 // 控制。更改这些属性值可修改 // 与程序集关联的信息。 [assembly: AllowPartiallyTrustedCallers()] [assembly: AssemblyTitle("ActiveX")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ActiveX")] [assembly: AssemblyCopyright("Copyright © 2012")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 使此程序集中的类型 // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, // 则将该类型上的 ComVisible 属性设置为 true。 [assembly: ComVisible(true)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("080c08e4-90eb-4ad6-a73f-c93fe6813680")] // 程序集的版本信息由下面四个值组成: // // 主版本 // 次版本 // 内部版本号 // 修订号 // // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, // 方法是按如下所示使用“*”: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ActiveX { [ComImport,GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IObjectSafety { [PreserveSig] int GetInterfaceSafetyOptions(ref Guid riid,[MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions,[MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); [PreserveSig()] int SetInterfaceSafetyOptions(ref Guid riid,[MarshalAs(UnmanagedType.U4)] int dwOptionSetMask,[MarshalAs(UnmanagedType.U4)] int dwEnabledOptions); } }
vs2008安装项目依赖ActiveX项目 输出类库,最后生成NontaxInstaller.msi和setup.exe
ActiveX项目生成属性中 已经 勾选了 “为COM互操作注册”
setup项目属性中 已经设置 RemovePreviousVersion属性设置为True
此处省略了打包成CAB文件的步骤,CABARC.EXE打包的
"D:\cab\CABARC.EXE" -s 6144 n D:\cab\NontaxInstaller.cab D:\cab\NontaxInstaller.msi D:\cab\NontaxInstaller.inf
---------NontaxInstaller.inf-----------------
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
hook1=hook1
[hook1]
run=msiexec.exe /i "%EXTRACT_DIR%\NontaxInstaller.msi" /qn
-----------------------------------------------------------------
第一次部署安装:客户端访问
客户端首次访问,插件可以正常安装,并且功能一切正常(抛开IE安全性设置不讲)
问题:
现在对插件功能扩展:
1.重新生成ActiveX项目的GUID,并且在代码中替换
2.修改setup安装项目版本号1.0.2(初始版本为1.0.1),此时productcode会自动重新生成一次
3.修改HTML测试网页,修改GUID和插件版本号
第二次测试:打开网页后 提示安装插件,安装后,网页显示的还是老版本插件,刷新也没有变化。
此时查看控制面板中 的 安装、卸载程序,发现新插件已经更新安装,并且插件版本号已经是第二次发布的版本号。
没有办法,在控制面板中卸载掉插件,重新打开网页,提示安装插件,安装成功,显示新版本插件,功能运行正常!!!
万分苦恼,查了很多资料,都是很老的帖子,介绍的内容页多数重复,根本没有自动更新的这个问题。
恳请各位大虾支招,谢谢!!
不要从新生成GUID
浏览器端检测ActiveX控件是否需要升级,是通过比对<object>标签的codebase属性值和本地HKEY_CLASSES_ROOT/CLSID/{GUID}/InstalledVersion键值是否相等来判断的。所以,如果要实现自动更新,需要手动添加该注册表项,并在每次升级控件时,相应更改该项键值。
右键点击安装项目,依次选择“视图->注册表”菜单,打开安装项目的注册表编辑界面,并在HKEY_CLASSES_ROOT节点下,建立CLSID/{GUID}/InstalledVersion注册表键路径
不能检测版号然后提示用户重新安装吗?重装的时候就可以先卸载
发布新版本后,浏览器会提示重新安装的,可是安装之后,浏览器还是显示旧版的插件,右键查看网页源代码,发现GUID和版本号都已经变化了,表示网页是更新过的,而且控制面板中 安装的插件版本 也变成新插件的版本号了,问题就是,浏览器不显示新插件
@飞扬Design:
难道是IE自动重装有问题,再写个卸载的在安装时先执行卸载,不知道行不行...
@向往-SONG: 感觉是注册表的问题,第一次安装顺利注册,第二次更新升级安装,好像就注册出问题了
缓存,该死的缓存!
去 IE缓存目录中删除所有的东西!
一定要自己手动去删除,不要用IE的清除缓存功能。
这个不是JS ,跟缓存没有关系,手动清理多次,无用