具有通用组件的 Wix 安装程序
wix installers with common component
我有 Web 应用程序,我想将其安装在 IIS 上。此应用程序支持插件架构。
它包括:
- 核心部分
- 插件A
- 插件 B
我想要 2 个安装程序 (msi)。一个用于插件 A,另一个用于插件 B。
每个安装程序还应该安装核心部分。因此,如果我 运行 插件 A 安装程序,它应该安装核心部分和插件 A 二进制文件。然后,如果我 运行 插件 B 的安装程序,它应该只安装插件 B 二进制文件。但是,如果 运行 插件 B 安装程序首先应该安装核心部分和插件 B 二进制文件。
我为核心部分使用了 WiX 合并模块项目,并为每个安装程序创建了 2 个 WiX 项目。但它并不如我所愿。
这是它的工作原理:
- 我 运行 插件 A 的安装程序(工作正常)
- 我 运行 插件 B 安装程序,它检测到产品已经安装,显示删除、修复、更改页面
- 我选择更改,我在功能树上看到 "Plugin A" 而不是 "Plugin B"
您可以在此处查看示例解决方案:https://github.com/bwojdyla/wixplugins
在调试配置中工作。维克斯 3.9,VS2012
我的合并模块(核心部分):
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Module Id="CoreModule" Language="1033" Version="1.0.0.0">
<Package Id="751e70eb-cf76-413b-b8c8-231a31f9c946" Manufacturer="test" InstallerVersion="200" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDER" Name="PluginInstaller">
<Component Id="CoreComp" Guid="{161F78E1-0ABD-4FCD-92FC-6095A45F78B3}">
<File Id="CoreFile" KeyPath="yes" Source=".\Core.txt" />
</Component>
</Directory>
</Directory>
</Module>
</Wix>
插件A:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{8E93D1E7-C05F-40A0-B737-C053C1EE3E0A}" Name="PluginInstaller" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="{9C7D28B4-FBAD-4FE6-A204-8F6A11D89792}"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="Cab1.cab" EmbedCab="yes" />
<UIRef Id="WixUI_FeatureTree"/>
<FeatureRef Id="ProductFeature">
<Feature Id="PluginA" Title="Plugin A" Level="1" AllowAdvertise="no">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</FeatureRef>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="PluginInstaller" />
<Merge Id="CoreModule" Language="1033" SourceFile="..\CoreModule\bin\Debug\CoreModule.msm" DiskId="1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="PluginAComp" Guid="{7641AF10-B2EF-4639-A0B4-34AE819CAD38}">
<File Id="PluginAFile" KeyPath="yes" Source=".\PluginA.txt" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
插件 B:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{8E93D1E7-C05F-40A0-B737-C053C1EE3E0A}" Name="PluginInstaller" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="{9C7D28B4-FBAD-4FE6-A204-8F6A11D89792}"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="Cab1.cab" EmbedCab="yes" />
<UIRef Id="WixUI_FeatureTree"/>
<FeatureRef Id="ProductFeature">
<Feature Id="PluginB" Title="Plugin B" Level="1" AllowAdvertise="no">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</FeatureRef>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="PluginInstaller" />
<Merge Id="CoreModule" Language="1033" SourceFile="..\CoreModule\bin\Debug\CoreModule.msm" DiskId="1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="PluginBComp" Guid="{D11704D9-9911-483A-B204-B2171DCB0E67}">
<File Id="PluginBFile" KeyPath="yes" Source=".\PluginB.txt" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
或者我应该使用其他 wix 功能来实现此目的?
Windows 安装程序通过它们的 GUID 识别和引用计数组件;所以基本上您需要做的是确保公共部件组件 ("core") 包含在具有相同组件 guid 的两个产品中。 IE。原则上,您不一定可以通过创建合并模块来实现这一点,但例如可以通过将 "core" 部分的代码#including 到两个模块中来实现。无论如何,合并模块很好 - 它基本上做或多或少相同的事情。
重要的是,您应该为 PluginA 和 PluginB 使用不同的产品 ID 和包 ID,否则它们在 Windows 安装程序中看起来是一样的(它通过它的 guid 识别正在安装的产品)。现在,当您尝试安装 B 时,它认为实际上是 A 被卸载了,因此您会收到此消息。
所以您可以尝试像这样更改您的产品 A/B 文件(请注意,我也省略了 "packageid" - 它是自动生成的,基本上所有 MSI 都应该有不同的包 ID ).
产品 A
<Product Id="{4D7828A0-F55C-4D26-9AA9-914FF646C55E}" Name="PluginInstallerA" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
产品 B
<Product Id="{E052B5C0-BB4D-4848-844C-2293059E9465}" Name="PluginInstallerB" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
这里对引用计数进行了详细的解释:
MSI Reference Counting: Two products install the same MSIs
在这些情况下,两个包总是安装核心部分。那是正常的情况。您不希望处于安装 A 和核心然后在没有核心的情况下安装 B 的情况,因为卸载 A 将删除 B 正在使用的核心。核心在两者中,因此引用计数意味着您可以同时安装两个,然后卸载一个,核心仍然存在。当 B 安装在 A 上时发生的所有事情要么什么都没有(因为文件版本相同并且它们位于相同的位置),要么更新了一些文件(因为最后安装的插件在公共位置更新了文件版本).正如 Nikolay 所说,您可以通过拥有一个核心部分(如在添加到两个 MSI 的合并模块中)或以其他方式确保基于组件 guid 的共享是正确的来安排所有这些工作。
我有 Web 应用程序,我想将其安装在 IIS 上。此应用程序支持插件架构。 它包括:
- 核心部分
- 插件A
- 插件 B
我想要 2 个安装程序 (msi)。一个用于插件 A,另一个用于插件 B。 每个安装程序还应该安装核心部分。因此,如果我 运行 插件 A 安装程序,它应该安装核心部分和插件 A 二进制文件。然后,如果我 运行 插件 B 的安装程序,它应该只安装插件 B 二进制文件。但是,如果 运行 插件 B 安装程序首先应该安装核心部分和插件 B 二进制文件。
我为核心部分使用了 WiX 合并模块项目,并为每个安装程序创建了 2 个 WiX 项目。但它并不如我所愿。
这是它的工作原理:
- 我 运行 插件 A 的安装程序(工作正常)
- 我 运行 插件 B 安装程序,它检测到产品已经安装,显示删除、修复、更改页面
- 我选择更改,我在功能树上看到 "Plugin A" 而不是 "Plugin B"
您可以在此处查看示例解决方案:https://github.com/bwojdyla/wixplugins 在调试配置中工作。维克斯 3.9,VS2012
我的合并模块(核心部分):
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Module Id="CoreModule" Language="1033" Version="1.0.0.0">
<Package Id="751e70eb-cf76-413b-b8c8-231a31f9c946" Manufacturer="test" InstallerVersion="200" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDER" Name="PluginInstaller">
<Component Id="CoreComp" Guid="{161F78E1-0ABD-4FCD-92FC-6095A45F78B3}">
<File Id="CoreFile" KeyPath="yes" Source=".\Core.txt" />
</Component>
</Directory>
</Directory>
</Module>
</Wix>
插件A:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{8E93D1E7-C05F-40A0-B737-C053C1EE3E0A}" Name="PluginInstaller" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="{9C7D28B4-FBAD-4FE6-A204-8F6A11D89792}"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="Cab1.cab" EmbedCab="yes" />
<UIRef Id="WixUI_FeatureTree"/>
<FeatureRef Id="ProductFeature">
<Feature Id="PluginA" Title="Plugin A" Level="1" AllowAdvertise="no">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</FeatureRef>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="PluginInstaller" />
<Merge Id="CoreModule" Language="1033" SourceFile="..\CoreModule\bin\Debug\CoreModule.msm" DiskId="1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="PluginAComp" Guid="{7641AF10-B2EF-4639-A0B4-34AE819CAD38}">
<File Id="PluginAFile" KeyPath="yes" Source=".\PluginA.txt" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
插件 B:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{8E93D1E7-C05F-40A0-B737-C053C1EE3E0A}" Name="PluginInstaller" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="{9C7D28B4-FBAD-4FE6-A204-8F6A11D89792}"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="Cab1.cab" EmbedCab="yes" />
<UIRef Id="WixUI_FeatureTree"/>
<FeatureRef Id="ProductFeature">
<Feature Id="PluginB" Title="Plugin B" Level="1" AllowAdvertise="no">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</FeatureRef>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="PluginInstaller" />
<Merge Id="CoreModule" Language="1033" SourceFile="..\CoreModule\bin\Debug\CoreModule.msm" DiskId="1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="PluginBComp" Guid="{D11704D9-9911-483A-B204-B2171DCB0E67}">
<File Id="PluginBFile" KeyPath="yes" Source=".\PluginB.txt" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
或者我应该使用其他 wix 功能来实现此目的?
Windows 安装程序通过它们的 GUID 识别和引用计数组件;所以基本上您需要做的是确保公共部件组件 ("core") 包含在具有相同组件 guid 的两个产品中。 IE。原则上,您不一定可以通过创建合并模块来实现这一点,但例如可以通过将 "core" 部分的代码#including 到两个模块中来实现。无论如何,合并模块很好 - 它基本上做或多或少相同的事情。
重要的是,您应该为 PluginA 和 PluginB 使用不同的产品 ID 和包 ID,否则它们在 Windows 安装程序中看起来是一样的(它通过它的 guid 识别正在安装的产品)。现在,当您尝试安装 B 时,它认为实际上是 A 被卸载了,因此您会收到此消息。
所以您可以尝试像这样更改您的产品 A/B 文件(请注意,我也省略了 "packageid" - 它是自动生成的,基本上所有 MSI 都应该有不同的包 ID ).
产品 A
<Product Id="{4D7828A0-F55C-4D26-9AA9-914FF646C55E}" Name="PluginInstallerA" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
产品 B
<Product Id="{E052B5C0-BB4D-4848-844C-2293059E9465}" Name="PluginInstallerB" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="eed33233-e773-45c2-87a1-ab349191a30a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
这里对引用计数进行了详细的解释: MSI Reference Counting: Two products install the same MSIs
在这些情况下,两个包总是安装核心部分。那是正常的情况。您不希望处于安装 A 和核心然后在没有核心的情况下安装 B 的情况,因为卸载 A 将删除 B 正在使用的核心。核心在两者中,因此引用计数意味着您可以同时安装两个,然后卸载一个,核心仍然存在。当 B 安装在 A 上时发生的所有事情要么什么都没有(因为文件版本相同并且它们位于相同的位置),要么更新了一些文件(因为最后安装的插件在公共位置更新了文件版本).正如 Nikolay 所说,您可以通过拥有一个核心部分(如在添加到两个 MSI 的合并模块中)或以其他方式确保基于组件 guid 的共享是正确的来安排所有这些工作。