我正在使用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”,则此文件也必须是组件的关键路径。
然后,对于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
,一个用于应用程序可执行文件,另一个用于其清单?
答案 0 :(得分:0)
隔离的COM :您需要的是隔离的COM组件,这与Win32程序集( WinSxS < / strong>)和.NET 程序集( GAC )。
快速建议:
我的2分:
Run this legacy application on a virtual machine instead!
问题解决了吗?(可能已解决问题)。
警告:以下内容写得很匆忙。稍后再检查。
这个(古老的)真正的专家是Wim Coenen-不知道他不再潜入这个标签了:
并排 :这两种类型的程序集是并排安装的 win32文件( WinSxS < / strong>)或 .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程序集 安装。参见下面的现实检查...
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完全相同的文件版本才能正常工作。 所有文件的版本正确。这并不是说人们没有成功使用该方法,而是我通常建议人们去虚拟化:依靠虚拟机来运行这些旧应用程序。
我对这个旧答案有更多的了解:What do I do when launching an application triggers repeating, endless Windows Installer self-repair?(请参阅无注册COM部分)。