1. 介紹
Wix Toolset是一個打包工具,用於將開發好的軟件或者三方庫打包成Windows安裝程序(Microsoft Installer,MSI)。這個工具本身是開源的,通過XML文件來配置打包屬性。使用方法是:
1. 首先需要編寫打包配置文件**.wxs,不妨命名為Sample.wxs,這個文件本身就是XML格式。
2. 然后Wix Toolset的candle.exe工具來“編譯”Sample.wxs。即執行candle.exe Sample.wxs
命令,該命令執行后會在同目錄下生成Sample.wixobj文件。
3. 使用Wix Toolset的light.exe工具來“鏈接”Sample.wixobj。即執行light.exe Sample.wixobj
命令,該命令執行后會在同目錄下生成Sample.msi,即我們安裝包文件。
4. 如果我們Sample.msi本身會依賴於一些框架,比如.Net Framework 4。而用戶可能沒有安裝.Net Framework 4,這時候可以再編寫一個ExeBundle.wxs(名字任意取),里面需要有<Bundle></Bundle>
標簽。然后“編譯”和“鏈接”就可以得到一個新的安裝包ExeBundle.exe,當安裝Sample.msi時如果沒有.Net Framework 4環境,自動安裝這個環境,有則不用安裝,后面我們會詳細說明。
2. 一個簡單的例子
先看一個官方給出的簡單的例子(參考: https://www.firegiant.com/wix/tutorial/getting-started/ ),如果想直接看打包文件夾為MSI的可以跳過這一節。
2.1 編寫SampleFirst.wxs
假設我們要打包如下3個文件為一個安裝包。
首先我們需要編寫打包配置文件SampleFirst.wxs,內容如下,SampleFirst.wxs與3個文件的同一目錄。
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<!--Id和UpgradeCode設置為GUID就可以,使用網站https://www.iamwawa.cn/guid.html就可以生成-->
<Product Name='Foobar 1.0' Id='096bf663-e5e4-4987-ad59-e5766d113ec3' UpgradeCode='096bf663-e5e4-4987-ad59-e5766d113ec3'
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
<!--設置MSI安裝包信息-->
<Package Id='*' Keywords='Installer'
Description="Acme's Foobar 1.0 Installer"
Comments='Foobar is a registered trademark of Acme Ltd.' Manufacturer='Acme Ltd.'
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<!--將資源放入MSI中,也可以將資源與MSI安裝包分割-->
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
<Property Id='DiskPrompt' Value="Acme's Foobar 1.0 Installation [1]" />
<!--改變INSTALLDIR初始值-->
<!--<Property Id="INSTALLDIR" Value="E:\\"/>-->
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='Acme' Name='Acme'>
<Directory Id='INSTALLDIR' Name='Foobar 1.0'>
<!-- 安裝的文件都放在這里面 -->
<!-- 文件FoobarAppl10.exe,還有Shortcut -->
<Component Id='MainExecutable' Guid='636d41d9-d950-4a82-90f7-e186d5ebcf24'>
<File Id='FoobarEXE' Name='FoobarAppl10.exe' DiskId='1' Source='FoobarAppl10.exe' KeyPath='yes'>
<Shortcut Id="startmenuFoobar10" Directory="ProgramMenuDir" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
<Shortcut Id="desktopFoobar10" Directory="DesktopFolder" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
</File>
</Component>
<!-- 文件Helper.dll -->
<Component Id='HelperLibrary' Guid='4e6393c0-e202-48ef-b87f-c89dab205350'>
<File Id='HelperDLL' Name='Helper.dll' DiskId='1' Source='Helper.dll' KeyPath='yes' />
</Component>
<!-- Manual.pdf -->
<Component Id='Manual' Guid='6b2bb045-d2ee-43e0-b6ca-f60f9a8f0c49'>
<File Id='Manual' Name='Manual.pdf' DiskId='1' Source='Manual.pdf' KeyPath='yes'>
<Shortcut Id="startmenuManual" Directory="ProgramMenuDir" Name="Instruction Manual" Advertise="yes" />
</File>
</Component>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="Foobar 1.0">
<Component Id="ProgramMenuDir" Guid="47a74487-0455-4084-926c-1ffe09958a01">
<RemoveFolder Id='ProgramMenuDir' On='uninstall' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes' />
</Component>
</Directory>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>
<!-- 這里可以設置安裝方式,如 完整,典型,自定義 安裝 -->
<Feature Id='Complete' Title='Foobar 1.0' Description='The complete package.'
Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR'>
<Feature Id='MainProgram' Title='Program' Description='The main executable.' Level='1'>
<ComponentRef Id='MainExecutable' />
<ComponentRef Id='HelperLibrary' />
<ComponentRef Id='ProgramMenuDir' />
</Feature>
<Feature Id='Documentation' Title='Description' Description='The instruction manual.' Level='1000'>
<ComponentRef Id='Manual' />
</Feature>
</Feature>
<!-- 很重要如果UI是WixUI_InstallDir那么這一句必須有 -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
<!-- 不同的UI參考 https://www.firegiant.com/wix/tutorial/user-interface/ui-wizardry/ -->
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
<Icon Id="Foobar10.exe" SourceFile="FoobarAppl10.exe" />
<!-- 安裝完成后可以自定義一些動作,比如打開軟件等 -->
<!-- 參考https://www.firegiant.com/wix/tutorial/events-and-actions/extra-actions/ -->
</Product>
</Wix>
然后打開cmd,“編譯”和“鏈接”SampleFirst.wxs,命令分別是candle SampleFirst.wxs
和light SampleFirst.wixobj -ext WixUIExtension
。由於使用了<UIRef />
,所以需要-ext WixUIExtension
。命令執行完后會生成如下文件,這樣就完成了打包。
3. 打包文件夾為MSI
比如我需要打包一個文件夾,如下圖。
3.1 使用heat.exe生成temp.wxs
由於該文件夾中有很多文件,所以我們需要用heat.exe
命令(參考 https://wixtoolset.org/documentation/manual/v3/overview/heat.html )來幫我們將這些文件生成對應的<Component/>
。使用命令:
heat.exe dir my_project -cg MyComponentGroup -gg -sfrag -template fragment -out temp.wxs
。
結果如下,可以看到執行命令后報錯了,但是其實不影響。
打開temp.wxs,然后將<Component/>
中文件的路徑改為有效路徑。就是將:
替換為
3.2 編寫Pack2MSI.wxs
然后編寫Pack2MSI.wxs,這里就需要將temp.wxs中的Component復制過去,內容如下:
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!--Id和UpgradeCode設置為GUID就可以,使用網站https://www.iamwawa.cn/guid.html就可以生成-->
<Product Name='MyProject' Id='176eb4a6-0272-4867-a445-d193e9ce0b77' UpgradeCode='7390005a-18ab-437d-bdaa-ef4c281ccf37'
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Companion Ltd.'>
<!--設置MSI安裝包信息-->
<Package Id='*' Keywords='Installer'
Description="MyProject 1.0.0 Installer"
Comments='MyProject is a Project of Company Ltd.' Manufacturer='Company Ltd.'
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<!--將資源放入MSI中,也可以將資源與MSI安裝包分割-->
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
<Property Id='DiskPrompt' Value="MyProject 1.0 Installation [1]" />
<!--改變INSTALLDIR初始值-->
<!--<Property Id="INSTALLDIR" Value="E:\\"/>-->
<Directory Id='TARGETDIR' Name='SourceDir'>
<!-- 安裝的文件被寫在了下面的INSTALLDIR -->
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="MyProject 1.0">
<Component Id="ProgramMenuDir" Guid="a910e463-5576-43c8-9260-dec72d82462e">
<RemoveFolder Id='ProgramMenuDir' On='uninstall' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='MyProject by Company Ltd.' KeyPath='yes' />
</Component>
</Directory>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>
<!-- 這里可以設置安裝方式,如 完整,典型,自定義 安裝 -->
<Feature Id='Complete' Title='FightCoordPy 1.0' Description='The complete package.'
Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR'>
<Feature Id='MainProgram' Title='Program' Description='The Environment and Source Code.' Level='1'>
<!-- 注意這里引用ComponentGroup -->
<ComponentGroupRef Id='MyComponentGroup' />
<ComponentRef Id='ProgramMenuDir' />
</Feature>
</Feature>
<!-- 很重要如果UI是WixUI_InstallDir那么這一句必須有 -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
<!-- 不同的UI參考 https://www.firegiant.com/wix/tutorial/user-interface/ui-wizardry/ -->
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
<!-- 這里也可以自定義安裝過程中顯示的內容,License文件、banner圖片、Dialog圖片-->
<!--<WixVariable Id="WixUILicenseRtf" Value="RelativePath\License.rtf" />
<WixVariable Id="WixUIBannerBmp" Value="RelativePathh\banner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="RelativePath\dialog.bmp" />-->
<!--<Icon Id="app.exe" SourceFile="" />-->
<!-- 安裝完成后可以自定義一些動作,比如打開軟件等 -->
<!-- 參考https://www.firegiant.com/wix/tutorial/events-and-actions/extra-actions/ -->
</Product>
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<!--公司ID文件夾-->
<Directory Id='CompanyID' Name='CompanyID'>
<!--項目ID文件夾-->
<Directory Id='INSTALLDIR' Name='MyProject 1.0'>
<!-- 安裝的文件都放在這里面 -->
<!-- 復制剛剛temp.wxs中第1個Fragment中的內容到這里 -->
<Directory Id="dir25AD93818D08B8A3D56C073B3A6AE911" Name="my_project">
<Component Id="cmpAA4738F5DD6DA7845B5FA95304F7DE78" Guid="{31F76004-D0AE-4C3B-BDB4-78776BB4C380}">
<File Id="fil86AA84748BC622BFC82215DD031047C9" KeyPath="yes" Source=".\my_project\ReadMe.docx" />
</Component>
<!-- 后面省略...... -->
</Directory>
</Directory>
</Directory>
</Directory>
</DirectoryRef>
</Fragment>
<!-- 復制剛剛temp.wxs中第2個Fragment中的內容到這里 -->
<Fragment>
<ComponentGroup Id="MyComponentGroup">
<ComponentRef Id="cmp6EC6E23C0D7DF340A98705574102B046" />
<ComponentRef Id="cmp88CDEC8D4664405F22A3335BE6DFFD6E" />
<ComponentRef Id="cmpCC9AE923AC764B56073C311FAB2E97CB" />
<!-- 后面省略...... -->
</ComponentGroup>
</Fragment>
</Wix>
3.3 生成MSI
運行命令candle Pack2MSI.wxs
和light Pack2MSI.wixobj -ext WixUIExtension
就打包成功了,如下圖:
然后可以安裝測試一下。
3.4 添加依賴程序
比如安裝Pack2MSI.msi需要依賴VC++ 2015 x64運行庫,即vc_redist.x64.exe。這時可以使用<Bundle/>
,首先看一下文件夾結構,如下圖所示。
3.4.1 編寫ExeBundle.wxs
內容如下:
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<!-- 配置安裝程序 -->
<Bundle Name="Test 2020 Setup" Version='1.0.0' UpgradeCode='033bc647-80f5-4010-80d6-ac0fc32368dc'>
<!-- 設置安裝程序的許可證 -->
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication
LicenseFile=".\dependencies\vc_redist.x64.rtf"/>
</BootstrapperApplicationRef>
<!-- 多個安裝包串行安裝 -->
<Chain>
<PackageGroupRef Id="DependencyPackage" />
<!--DownloadURL="https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe"-->
<!--<ExePackage
SourceFile=".\packages\shared\vc_redist.x64.exe"
InstallCommand="/q /ACTION=Install"
RepairCommand="/q ACTION=Repair /hideconsole"
UninstallCommand="/q ACTION=Uninstall /hideconsole"
InstallCondition="VersionNT64 AND VersionNT >= v5.1" />
-->
<!-- 這是我們的安裝包,DisplayInternalUI表示是否顯示Pack2MSI.msi原始的安裝UI,Visible表示安裝后是否顯示在控制面板上 -->
<MsiPackage
SourceFile=".\Pack2MSI.msi"
Id="SampleFirstMSI"
DisplayInternalUI="yes"
Visible="yes"
Permanent="no"
InstallCondition="VersionNT64 AND VersionNT >= v5.1" />
</Chain>
</Bundle>
<Fragment>
<!-- 先判斷VC++ 2015 x64 是否安裝了 -->
<util:RegistrySearch
Variable="vcRedist2015Exist"
Root="HKLM"
Key="SOFTWARE\Classes\Installer\Dependencies\{323dad84-0974-4d90-a1c1-e006c7fdbb7d}"
Result="exists"/>
<PackageGroup Id="DependencyPackage">
<!--DownloadURL="https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe"-->
<!-- 注意這里的InstallCondition,表示vc_redist.x64.exe只能是64位,Windows XP 並且沒有安裝vc_redist.x64.exe時候才安裝 -->
<ExePackage
SourceFile=".\dependencies\vc_redist.x64.exe"
InstallCommand="/q /ACTION=Install"
RepairCommand="/q ACTION=Repair /hideconsole"
UninstallCommand="/q ACTION=Uninstall /hideconsole"
InstallCondition="VersionNT64 AND VersionNT >= v5.1 AND vcRedist2015Exist = 0" />
</PackageGroup>
</Fragment>
</Wix>
3.4.2 生成ExeBundle.exe
分別執行命令:
candle ExeBundle.wxs -ext WixBalExtension -ext WixUtilExtension
light ExeBundle.wixobj -ext WixBalExtension -ext WixUtilExtension
就可以得到安裝包ExeBundle.exe。 運行ExeBundle.exe可以得到如圖所示的頁面
如有問題,歡迎斧正和討論。
參考
1. https://www.firegiant.com/wix/tutorial/getting-started/
2. https://blog.csdn.net/zerg_nick/article/details/102636516