【问题标题】:WiX: Component rules for installing an application with an application manifestWiX:使用应用程序清单安装应用程序的组件规则
【发布时间】:2019-03-02 19:04:47
【问题描述】:

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

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

为此,我创建了所需的清单文件,这些文件将用于在应用程序加载和使用库时查找所有 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,它告诉操作系统这个应用程序依赖于哪些程序集。所以我还创建了必要的清单文件。现在我需要创建一个(或多个)用于部署应用程序及其清单的组件。

根据File/@Assembly的VS intellisense:

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

然后,对于File/@AssemblyManifest

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

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

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

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

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

显然,我不希望我的应用程序安装到 GAC 中(而且,我认为不应该这样,因为我将 File/@Assembly 设置为 win32)。问题是,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* 属性并创建两个Component,一个用于应用程序可执行文件,另一个用于其清单?

【问题讨论】:

  • 您解决过这个问题吗?我面临同样的问题,Wix 中关于 Assembly 属性的文档有点缺乏。该文件必须存在于目标中还是在编译时存在?
  • @abbottdev 不,抱歉。我从来没有从任何人那里得到任何答案,也没有任何运气搜索过 Google 或 Bing。
  • @abbottdev 在下面写了一个答案。

标签: wix windows-installer


【解决方案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 Markup:只需将 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 正常工作所涉及的文件版本完全相同。 所有文件版本正确。这并不是说人们没有成功使用这种方法,但我一般建议人们转而使用虚拟化:依靠虚拟机来运行这些遗留应用程序

我有这个带有更多上下文的旧答案:What do I do when launching an application triggers repeating, endless Windows Installer self-repair?(请参阅无注册 COM 部分)。

【讨论】:

  • 感谢您回答一个非常古老的问题。从 Wix 文档中不清楚我试图做的只是针对 SxS 或 GAC 的程序集。这是针对工业控制器软件的,因此不能接受虚拟机。但是,将 COM 库和清单安装在同一个文件夹中是完全可行的,我认为这是我最终在不知道这样做是否正确 的情况下所做的事情。再次感谢!
  • 我意识到这是一个老问题,但我想我会把它写下来以备重用。 根据我的经验,这种孤立的 COM 东西在实践中非常困难。拥有源代码访问权限的人似乎最终成功了。我想这是允许反复试验的可调试性。我还想知道是否可以按照您尝试的方式通过 WinSxS 安装来隔离 COM - 作为并行调用,而不仅仅是本地文件夹调用?我从未见过或尝试过,并且操作系统加载程序在每个(或大多数)Windows 操作系统版本中都略有不同,所以我想这是一项艰苦的工作?不确定。
猜你喜欢
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
  • 2010-10-22
相关资源
最近更新 更多