Msi 安装程序运行自定义操作但留下文件进行安装
Msi Installer Runs custom Action but leaves File for Installation
我有以下 Wix 文件,应该安装 C:\SampleProgram
中的内容。生成的 msi 应该安装为 msiexec /i installer.msi IPADDRESS="1.1.1.1"
。参数 IPADDRESS
由自定义操作获取,它将在程序安装自身的文件夹中生成如下配置文件。
{
"ip" : "1.1.1.1"
}
问题是生成的安装文件在我的一台机器上工作正常,但它只在另一台机器上创建一个配置文件。成功安装 MSI 的文件夹将包含我的 wix 文件的 ComponentGroup
下定义的所有 Component
文件。如果安装成功,安装程序会将所有这些组件复制到已安装文件夹中。尽管它没有安装文件,但它 运行 自定义操作。
给出详细日志 here。
如果搜索 Component: BoostThreadLibrary ,我会得到 Installed: Absent,根据给定 here 表示 当前未安装组件或功能。。
是我机器的问题还是这个代码的问题。
我在下面附上了 wix 文件:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SampleProgram" Language="1033" Version="3.0.0" Manufacturer="Learning" UpgradeCode="a0265d05-8e65-4af2-98e1-a675b728dd2d">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="SampleProgram" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="WindowsVolume">
<Directory Id="INSTALLFOLDER" Name="SampleProgram" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent">
<File
Id="LPAEXE"
Name="lpa.exe"
DiskId="1"
Source="$(var.lpa.TargetPath)"
Vital="yes"
KeyPath="yes" />
<?if $(var.Configuration) = "Release"?>
<ServiceInstall Id="ServiceInstaller" Type="ownProcess" Vital="yes"
Name="LearningService" DisplayName="LearningService"
Description="How to make a Service" Start="auto"
Account="LocalSystem" ErrorControl="normal" Interactive="no" />
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall"
Name="LearningService" Wait="yes" />
<?endif?>
</Component>
<Component Id="BoostThreadLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_thread-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_thread-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostSystemLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_system-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_system-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostChronoLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_chrono-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_chrono-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostFileSystemLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_filesystem-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_filesystem-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostDateTimeLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_date_time-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_date_time-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostZlibLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_zlib-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_zlib-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostIOStreamLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_iostreams-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_iostreams-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostRegexLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_regex-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_regex-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="libeay32">
<File Source ="C:\OpenSSL-Win32\libeay32.dll" />
</Component>
<Component Id="ssleay32">
<File Source ="C:\OpenSSL-Win32\ssleay32.dll" />
</Component>
<Component Id="czmq">
<?if $(var.Configuration) = "Debug"?>
<File Source ="..\..\ext_library\zmq\czmq\czmq-2.1.0\lib\Win32\DebugDLL\czmq.dll" />
<?else?>
<File Source ="..\..\ext_library\zmq\czmq\czmq-2.1.0\lib\Win32\ReleaseDLL\czmq.dll" />
<?endif?>
</Component>
<Component Id="log4cplus">
<?if $(var.Configuration) = "Debug"?>
<File Source ="..\..\ext_library\log4cplus\bin\Debug\log4cplusD.dll" />
<?else?>
<File Source ="..\..\ext_library\log4cplus\bin\Release\log4cplus.dll" />
<?endif?>
</Component>
<Component Id="libzmq">
<?if $(var.Configuration) = "Debug"?>
<File Source ="..\..\ext_library\zmq\zeromq-4.0.3\lib\Win32\Debug\libzmq.dll" />
<?else?>
<File Source ="..\..\ext_library\zmq\zeromq-4.0.3\lib\Win32\Release\libzmq.dll" />
<?endif?>
</Component>
<Component Id="SSL_Crt_File">
<File Source ="..\..\src\keys\ca.crt" />
</Component>
</ComponentGroup>
<Binary Id="SetupCA" SourceFile="..\..\ext_library\SetupCA\SetupCA\bin\Release\SetupCA.CA.dll"/>
<CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
<InstallExecuteSequence>
<Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
</InstallExecuteSequence>
</Fragment>
</Wix>
您的问题的核心是自定义操作的时间安排:
<CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
<InstallExecuteSequence>
<Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
</InstallExecuteSequence>
作为安排在 InstallFinalize
之前的即时操作,到此自定义操作 运行 时不会对文件进行任何更改。虽然这对于卸载来说可能很重要,但这可能与您想要的安装相反。
要读取由您的安装安装的文件,您应该安排您的操作 Execute="deferred"
,并在 InstallFiles
之后的某个时间。如果你在系统位置修改项目,它也应该是Impersonate="No"
,它只在延迟执行上下文中有效。
请注意,一旦您的操作被推迟,您将必须通过 CustomActionData
访问属性。
我不知道为什么,但是将 upgrade code
更改为其他 GUID
确实解决了问题。
我有以下 Wix 文件,应该安装 C:\SampleProgram
中的内容。生成的 msi 应该安装为 msiexec /i installer.msi IPADDRESS="1.1.1.1"
。参数 IPADDRESS
由自定义操作获取,它将在程序安装自身的文件夹中生成如下配置文件。
{
"ip" : "1.1.1.1"
}
问题是生成的安装文件在我的一台机器上工作正常,但它只在另一台机器上创建一个配置文件。成功安装 MSI 的文件夹将包含我的 wix 文件的 ComponentGroup
下定义的所有 Component
文件。如果安装成功,安装程序会将所有这些组件复制到已安装文件夹中。尽管它没有安装文件,但它 运行 自定义操作。
给出详细日志 here。
如果搜索 Component: BoostThreadLibrary ,我会得到 Installed: Absent,根据给定 here 表示 当前未安装组件或功能。。
是我机器的问题还是这个代码的问题。
我在下面附上了 wix 文件:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SampleProgram" Language="1033" Version="3.0.0" Manufacturer="Learning" UpgradeCode="a0265d05-8e65-4af2-98e1-a675b728dd2d">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="SampleProgram" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="WindowsVolume">
<Directory Id="INSTALLFOLDER" Name="SampleProgram" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent">
<File
Id="LPAEXE"
Name="lpa.exe"
DiskId="1"
Source="$(var.lpa.TargetPath)"
Vital="yes"
KeyPath="yes" />
<?if $(var.Configuration) = "Release"?>
<ServiceInstall Id="ServiceInstaller" Type="ownProcess" Vital="yes"
Name="LearningService" DisplayName="LearningService"
Description="How to make a Service" Start="auto"
Account="LocalSystem" ErrorControl="normal" Interactive="no" />
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall"
Name="LearningService" Wait="yes" />
<?endif?>
</Component>
<Component Id="BoostThreadLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_thread-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_thread-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostSystemLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_system-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_system-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostChronoLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_chrono-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_chrono-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostFileSystemLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_filesystem-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_filesystem-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostDateTimeLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_date_time-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_date_time-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostZlibLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_zlib-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_zlib-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostIOStreamLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_iostreams-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_iostreams-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="BoostRegexLibrary">
<?if $(var.Configuration) = "Debug"?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_regex-vc100-mt-gd-1_55.dll" />
<?else?>
<File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_regex-vc100-mt-1_55.dll" />
<?endif?>
</Component>
<Component Id="libeay32">
<File Source ="C:\OpenSSL-Win32\libeay32.dll" />
</Component>
<Component Id="ssleay32">
<File Source ="C:\OpenSSL-Win32\ssleay32.dll" />
</Component>
<Component Id="czmq">
<?if $(var.Configuration) = "Debug"?>
<File Source ="..\..\ext_library\zmq\czmq\czmq-2.1.0\lib\Win32\DebugDLL\czmq.dll" />
<?else?>
<File Source ="..\..\ext_library\zmq\czmq\czmq-2.1.0\lib\Win32\ReleaseDLL\czmq.dll" />
<?endif?>
</Component>
<Component Id="log4cplus">
<?if $(var.Configuration) = "Debug"?>
<File Source ="..\..\ext_library\log4cplus\bin\Debug\log4cplusD.dll" />
<?else?>
<File Source ="..\..\ext_library\log4cplus\bin\Release\log4cplus.dll" />
<?endif?>
</Component>
<Component Id="libzmq">
<?if $(var.Configuration) = "Debug"?>
<File Source ="..\..\ext_library\zmq\zeromq-4.0.3\lib\Win32\Debug\libzmq.dll" />
<?else?>
<File Source ="..\..\ext_library\zmq\zeromq-4.0.3\lib\Win32\Release\libzmq.dll" />
<?endif?>
</Component>
<Component Id="SSL_Crt_File">
<File Source ="..\..\src\keys\ca.crt" />
</Component>
</ComponentGroup>
<Binary Id="SetupCA" SourceFile="..\..\ext_library\SetupCA\SetupCA\bin\Release\SetupCA.CA.dll"/>
<CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
<InstallExecuteSequence>
<Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
</InstallExecuteSequence>
</Fragment>
</Wix>
您的问题的核心是自定义操作的时间安排:
<CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
<InstallExecuteSequence>
<Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
</InstallExecuteSequence>
作为安排在 InstallFinalize
之前的即时操作,到此自定义操作 运行 时不会对文件进行任何更改。虽然这对于卸载来说可能很重要,但这可能与您想要的安装相反。
要读取由您的安装安装的文件,您应该安排您的操作 Execute="deferred"
,并在 InstallFiles
之后的某个时间。如果你在系统位置修改项目,它也应该是Impersonate="No"
,它只在延迟执行上下文中有效。
请注意,一旦您的操作被推迟,您将必须通过 CustomActionData
访问属性。
我不知道为什么,但是将 upgrade code
更改为其他 GUID
确实解决了问题。