2

我正在使用 WiX 3.7 编写安装程序。安装程序将安装一个旧的 VB6 程序(它是一个供应商专有程序,我没有源代码)。因此,该程序使用了一些未随最新版本的 Windows 安装的旧 COM 库(例如 Windows 7 及更高版本——不确定 Vista 或 XP)。

由于我最近了解到 COM 库现在可以使用免注册 COM 注册来私下安装而无需全局系统注册,这正是我打算为那些不再随 Windows 操作系统分发的 COM 库所做的。

为此,我创建了所需的清单文件,这些文件将用于在应用程序加载和使用库时查找所有 COM 注册信息。我为这些库创建了 MSI 组件。这是这两个库的相关 WiX 标记(我已经删除了组件的 GUID,因此没有人为自己的安装程序复制它们):

<Component Id="C__MsComm32.ocx" Guid="PUT-YOUR-GUID-HERE" DiskId="1">
  <File Id="F__MsComm32.ocx" Vital="yes" KeyPath="yes"
        Assembly="win32"
        AssemblyApplication="F__MyApp.exe"
        AssemblyManifest="F__MsComm32.sxs.manifest"
        Name="mscomm32.ocx" Source="[to be filled in]" />
  <File Id="F__MsComm32.sxs.manifest" Vital="yes" KeyPath="no"
        Name="mscomm32.sxs.manifest" Source="[to be filled in]" />
</Component>
<Component Id="C__threed32.ocx" Guid="PUT-YOUR-GUID-HERE" DiskId="1">
  <File Id="F__threed32.ocx" Vital="yes" KeyPath="yes"
        Assembly="win32"
        AssemblyApplication="F__MyApp.exe"
        AssemblyManifest="F__threed32.sxs.manifest"
        Name="threed32.ocx" Source="[to be filled in]"  />
  <File Id="F__threed32.sxs.manifest" Vital="yes" KeyPath="no"
        Name="threed32.sxs.manifest" Source="[to be filled in]" />
</Component>

为了使所有这些工作,我还需要为应用程序可执行文件提供一个清单文件,称为MyApp.exe.manifest告诉操作系统此应用程序依赖于哪些程序集。所以我还创建了必要的清单文件。现在我需要创建一个(或多个)用于部署应用程序及其清单的组件。

根据 VS 智能感知File/@Assembly

指定此文件是需要安装到全局程序集缓存 (GAC) 中的 Win32 程序集还是 .NET 程序集。如果值为“.net”或“win32”,该文件也必须是组件的关键路径。

然后,对于File/@AssemblyManifest

指定描述程序集的清单文件的文件标识符。清单应与其描述的程序集位于同一组件中。只有在将 Assembly 属性设置为“.net”或“win32”时才能指定此属性。

这一切都很好,我完全理解这一切。因此,对于我File在 WiX 中的应用程序元素,到目前为止,我有这个:

<File Id="F__MyApp.exe" Vital="yes" KeyPath="yes"
      Assembly="win32"
      AssemblyManifest="F__MyApp.exe.manifest" />

现在,我不明白的是File/@AssemblyApplication属性的智能感知:

指定应用程序文件的标识符。该程序集将被隔离到与应用程序文件相同的目录中。如果此属性不存在,则程序集将安装到全局程序集缓存 (GAC)。

显然,我不希望我的应用程序安装到 GAC 中(而且,我认为它不应该是因为我设置File/@Assemblywin32)。问题是,属性值可以File/@AssemblyApplication指向其父元素的@Id属性吗?例如:

<Component Id="C__MyApp.exe" Guid="PUT-YOUR-GUID-HERE" DiskId="1">
    <File Id="F__MyApp.exe" Vital="yes" KeyPath="yes"
          Assembly="win32"
          AssemblyManifest="F__MyApp.exe.manifest"
          AssemblyApplication="F__MyApp.exe" />
    <!-- @AssemblyApplication references it's parent element's @Id attribute. -->
    <File Id="F__MyApp.exe.manifest" Vital="yes" KeyPath="no"
          Name="MyApp.exe.manifest" Source="[to be filled in]" />
</Component>

这是Component为包含应用程序清单的应用程序创作元素的正确方法吗?还是我应该忘记设置各种Assembly*属性并创建两个Components,一个用于应用程序可执行文件,另一个用于其清单?

4

1 回答 1

1

隔离 COM:您需要的是一个隔离的 COM 组件,这是与 Win32 程序集 ( WinSxS ) 和 .NET 程序集 ( GAC )不同的概念。

快速建议:

我的 2 美分:Run this legacy application on a virtual machine instead!问题解决了吗?(问题可能已消除)。


警告:以下是仓促写的。我稍后会再次检查。

(旧的)这方面的真正专家是Wim Coenen - 不确定他是否还潜伏着这个标签:


Side-By-Side:这两种类型的程序集分别是并排安装的win32 文件( WinSxS ) 或并排安装的.NET 程序集( GAC )。这意味着旧的 Win32 文件(本机代码)和现代 .NET 程序集(托管代码- 需要 .NET 运行时)。Side-by-side obviously means that different versions of the same file (referred to as assembly) can co-exist and you can load the one you require by means of a manifest.

隔离 COM:隔离 COM 是完全不同的东西。It is the installation and invocation of COM servers without any registry entanglements - all happening from within the same installation folder. 我经常将其称为“无注册 COM”——也许是一个奇怪的术语。

这意味着您可以从本地安装文件夹中加载不兼容的 COM 服务器版本,以便使用它们的任何二进制文件。您需要做的就是将 COM 服务器及其清单转储到本地安装文件夹中。无需安装 Win32 或 .NET 程序集。请参阅下面的实际检查...

  • 这“解决”了 COM 的一个巨大问题,即 COM 服务器的每台机器或全局注册特性。换句话说,通常只安装了一个版本的 COM 服务器(尽管在技术上可以安装不同风格的 COM 服务器,但通常不会这样做——GUID 和 ID 更改的噩梦)。
  • 它还有助于将您的应用程序与在注册表中触发 COM 注册冲突的脏包、安装程序、脚本和应用程序隔离开来。自从 COM 到来以来,这是一个非常成问题的问题。

WiX 标记:只需将 COM 服务器和清单文件安装在同一文件夹中:

<Component>
  <File Source="mscomm32.ocx" />
  <File Source="mscomm32.sxs.manifest" />
</Component>
<Component>
  <File Source="threed32.ocx"  />
  <File Source="threed32.sxs.manifest" />
</Component>

现实检查:我的经验是,当您无法访问相关源代码时,很难让孤立的 COM 工作。原因是COM是二进制标准/二进制重用。据我了解,您需要与此隔离 COM 正常工作所涉及的文件版本完全相同。正确版本的所有文件。这并不是说人们没有成功使用这种方法,但我一般建议人们转而使用虚拟化:依靠虚拟机来运行这些遗留应用程序

我有这个带有更多上下文的旧答案:启动应用程序触发重复、无休止的 Windows Installer 自我修复时该怎么办?(参见无注册 COM 部分)。

于 2019-03-01T16:43:03.193 回答