如何推出一个用VB6编写的ActiveX控件的新版本

6

我需要维护一个用VB6编写的旧的ActiveX控件。

因为我们为它开发了一些新功能,现在我需要将这个新版本推送给用户。如何以最不影响用户的方式完成?

该控件嵌入代码如下:

<OBJECT classid="clsid:..." CODEBASE="activex/plugin/myOCX.CAB#version=1,0,0,42">
    <PARAM name="RunOnLoad" value="true"></PARAM>
    [...]
</OBJECT>

不,当我将#version更改为实际版本(1,0,0,80)时,它并没有改变任何东西。IE仍然加载旧版本(通过警报OCX版本的函数可以检查)。
只有当我从计算机中删除OCX,然后加载页面时,它才会输出新版本。
显然,用户不能也不应该这样做。因此问题是:一旦部署到服务器上,我如何有效地强制我的用户使用新版本?

您能否发布包括所有子键和值的“HKEY_CLASSES_ROOT\CLSID{<clsid>}”内容? - Ilya Kurnosov
你能否同时张贴.INF文件的内容(它应该在.CAB文件中)? - Ilya Kurnosov
是因为你需要将井号 # 改成问号吗? - Tyler Crompton
2个回答

1

由于版本问题,当您从计算机中删除现有版本后,IE成功下载并安装组件,这就是版本控制的问题。在这一点上,我可以想到几种情况。

情况1:.INF文件错误

打开您的.CAB文件。您将看到其中的.INF文件。打开此.INF文件并找到[<component name>.ocx]部分。检查FileVersion=...的值,它应该是FileVersion=1,0,0,80。我发现,如果您通过Package & Deployment Wizard之前生成的.BAT脚本更新现有的.CAB文件,则此值不会自动更新。

情况2:测试环境被构建过程污染

我能想到的另一种情况是,您正在测试与您用于构建控件新版本的同一台计算机。在这种情况下,您的控件可能已被构建过程注册。了解COM激活是如何工作的?对于理解有所帮助。不过,最好在除构建服务器外的其他计算机上进行测试。

可能性1:创建了名为AppID的命名值在HCKR\CLSID\{clsid}注册表键下的构建过程。
根据KB167597

以下是如何控制<OBJECT>标记的组件下载的伪代码:

   Check the Registry for CLSID
   If CLSID of OBJECT is NOT found in the registry
      Download OBJECT
   Else If no #Version specified in CODEBASE tag
      Use OBJECT installed on system
   Else
      Check InprocServer32 key for location of installed component
      If File version of installed component < CODEBASE #Version Tag
         Download OBJECT

以上顺序有几个例外情况。如果在CLSID下找到AppID密钥,则该组件通常是通过DCOM注册运行的,不会被更新。此外,已安装版本密钥优先于文件版本。这用于Java类和非PE(便携式可执行)文件。
为了确认这个想法,请检查您在测试中使用的计算机上是否有组件的AppID注册表值。您的用户很可能不会在其计算机上为CLSID设置AppID。当然,除非您的组件在至少另一种不同的情况下使用。Larry Osterman在他的博客文章When do you need an APPID in your COM registration?中提到了这一点。如果您不确定AppID是什么,请参阅this MSDN blog post

如何查找是否为CLSID设置了AppID?打开注册表编辑器regedt32,并检查HKEY_CLASSES_ROOT\CLSID\{<clsid>}键下的值。查找类型为REG_SZAppId命名值。

可能性2:构建过程更改了HCKR\CLSID\{clsid}\InprocServer32注册表键的默认值

检查HCKR\CLSID\{clsid}\InprocServer32注册表键的默认值((Default))。如果它指向您用作组件编译过程输出的位置,则很可能是在构建过程中设置的(除非您直接将构建结果放在C:\WINDOWS\Downloaded Program Files中,我真的很怀疑)。操作系统使用此值来确定在COM组件激活时要使用哪个二进制文件。运行regsvr32 /u <path to the .ocx created during compilation>,然后使用网页重新运行测试。


如果没有任何帮助,您需要更仔细地调查该问题。启动进程监视器,要求其跟踪IE进程的注册表和文件系统活动,并查看IE如何决定(不)更新您的控件。收集到的跟踪信息中有趣的信息应该会在查询控件的CLSID之后立即出现。

很遗憾,开发机与用户以及测试服务器/机器完全断开连接。 - F.P
我在哪里可以找到这个AppId?进程监视器并没有真正帮助我,因为当我打开测试页面时,IE执行了成千上万次操作,我不知道该看什么。 - F.P
好的,现在变得非常奇怪了...这两个CLSIDs都没有在HKEY_CLASSES_ROOT\CLSID中注册。 - F.P
@FlorianPeschka 这很奇怪。如果没有其他问题,当您加载带有控件的网页并让IE安装它时,必须创建HKCR\CLSID\{clsid}键。您的.cab文件内必须有.inf文件。它是否具有[AddToRegistry]部分?您如何生成.cab文件?坦白地说,我从未使用过除Package&Deployment Wizard之外的任何东西。 - Ilya Kurnosov
@FlorianPeschka 好的,我想到了另一种可能性并更新了我的帖子。但是,如果没有相应的 HKCR\CLSID\{clsid} 键,我看不出你的组件可以工作的方式。 - Ilya Kurnosov
看起来我实际上需要完全更改CLSID,以便客户端可以正确安装它。我猜某些组策略在某种程度上阻止了更新。至于XP机器,我实际上不得不为它们创建一个MSI安装程序,才能安装OCX。Windows7 Internet Explorer(虽然与XP上的版本完全相同)可以从Web上正确安装它。非常奇怪的事情。我会接受您的答案,因为它引导我走上了正确的道路,尽管实际错误没有被涵盖在内。但我认为我很难知道到底出了什么问题... - F.P

0

最好直接打破兼容性。

打开项目属性,从组件选项卡中,将版本兼容性更改为无兼容性。编译后,将您的clsid更改为匹配新的值。


我已经完成了这个任务 - 现在我有了一个新的CLSID,但是IE(在Windows XP上)不再安装它。是否有一种手动安装OCX的方法? - F.P
@FlorianPeschka:你可以使用regsvr32.exe来安装旧版本,方法与安装新版本相同。 - C-Pound Guru
好的,我从未安装过旧版本。它已经存在了大约10年,从未更改过。所以现在,没有人知道它是如何安装的。它似乎可以在Windows 7机器上自动工作,它们将其放在“下载文件”文件夹中,但在Windows XP中不会发生这种情况。 - F.P
@C-PoundGuru,注册组件是IE的工作。这种部署方案的整个重点在于使用户无需运行任何安装程序。 - Ilya Kurnosov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接