首页 新闻 会员 周边 捐助

ActiveX插件自动更新的问题,困扰很久,求助!

0
悬赏园豆:100 [已解决问题] 解决于 2013-12-27 09:28

因项目需要,用c#制作了一个ActiveX插件,功能很简单,控件已实现客户端安装,这些都没问题!我贴的代码是简化了功能的,具体业务没有写,太多。

View Code
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
AssemblyInfo.cs
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")]
IObjectSafety.cs
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和插件版本号

第二次测试:打开网页后 提示安装插件,安装后,网页显示的还是老版本插件,刷新也没有变化。

此时查看控制面板中 的 安装、卸载程序,发现新插件已经更新安装,并且插件版本号已经是第二次发布的版本号。

没有办法,在控制面板中卸载掉插件,重新打开网页,提示安装插件,安装成功,显示新版本插件,功能运行正常!!!

万分苦恼,查了很多资料,都是很老的帖子,介绍的内容页多数重复,根本没有自动更新的这个问题。

恳请各位大虾支招,谢谢!!

飞扬Design的主页 飞扬Design | 初学一级 | 园豆:58
提问于:2012-10-26 17:34
< >
分享
最佳答案
0

不要从新生成GUID

浏览器端检测ActiveX控件是否需要升级,是通过比对<object>标签的codebase属性值和本地HKEY_CLASSES_ROOT/CLSID/{GUID}/InstalledVersion键值是否相等来判断的。所以,如果要实现自动更新,需要手动添加该注册表项,并在每次升级控件时,相应更改该项键值。

右键点击安装项目,依次选择“视图->注册表”菜单,打开安装项目的注册表编辑界面,并在HKEY_CLASSES_ROOT节点下,建立CLSID/{GUID}/InstalledVersion注册表键路径

收获园豆:60
小兵仔 | 小虾三级 |园豆:1240 | 2013-10-18 15:20
其他回答(2)
0

不能检测版号然后提示用户重新安装吗?重装的时候就可以先卸载

收获园豆:20
向往-SONG | 园豆:4853 (老鸟四级) | 2012-10-26 21:23

发布新版本后,浏览器会提示重新安装的,可是安装之后,浏览器还是显示旧版的插件,右键查看网页源代码,发现GUID和版本号都已经变化了,表示网页是更新过的,而且控制面板中  安装的插件版本 也变成新插件的版本号了,问题就是,浏览器不显示新插件

支持(0) 反对(0) 飞扬Design | 园豆:58 (初学一级) | 2012-10-26 21:25

@飞扬Design: 

难道是IE自动重装有问题,再写个卸载的在安装时先执行卸载,不知道行不行...

支持(0) 反对(0) 向往-SONG | 园豆:4853 (老鸟四级) | 2012-10-26 21:41

@向往-SONG: 感觉是注册表的问题,第一次安装顺利注册,第二次更新升级安装,好像就注册出问题了

支持(0) 反对(0) 飞扬Design | 园豆:58 (初学一级) | 2012-10-28 21:17
0

缓存,该死的缓存!

去 IE缓存目录中删除所有的东西!

一定要自己手动去删除,不要用IE的清除缓存功能。

收获园豆:20
Alvin | 园豆:828 (小虾三级) | 2012-10-26 21:57

这个不是JS  ,跟缓存没有关系,手动清理多次,无用

支持(0) 反对(0) 飞扬Design | 园豆:58 (初学一级) | 2012-10-28 21:16
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册