使用wix制作安裝包


 公司產品的安裝包原先是用installshield開發,但是我們采用的installshiled版本是installshiled 2008,無法很好兼容windows 10.公司又不想花錢對其升級。討論下來有必要使用免費工具重新構建開發包。原來產品安裝包是msi格式,比較下,wix是最好的選擇。

最終的安裝包將會包含5種語言包括界面和EULA.主要功能包括通過custom action檢查產品序列號,升級(需要將原先程序退出),自動安裝.net 4.0 framework(主要考慮在產品依然需要運行在windows xp和windows 7上)

我們使用wix3.11集成到visual studio 2017中。 wix安裝包可以從SourceForge Wix網站下載。

安裝包項目結構分為6個目錄和一個主文件

 

  • CustomActions:每個custom action的定義在一個wix fragment中,一個wsx文件包含一個fragment
  • Fragments:包含由heat.exe自動生成的fragment和手動生成的修改注冊表的fragment
  • Includes:定義變量的wix文件,每個wsx文件都應該include這個wix文件
  • Lang:字符串國際化
  • Packages:保存生成的msi文件
  • Resources:msi需要的資源文件,如icon,bmp
  • Product.wsx:安裝包主文件

 

wix文件

主要定義安裝包腳本需要用到變量,使用這些變量的wsx文件應該include 這個頭文件

<?include "..\includes\ScanAppVariables.wxi"?>

當然可以在項目屬性中定義一個變量 properties->Build->“Define preprocessor variables” .但如果多個開發者同時添加一些變量可能導致修改項目文件時產生沖突

ScanAppVariables.wsx

<?xml version="1.0" encoding="utf-8"?>
<Include>
	<!-- TODO: Put your code here. -->
  <?define MajorVersion = "1"?>
  <?define MinorVersion = "1"?>
  <?define PatchVersion = "1"?>
  <?define VersionNumber = "$(var.MajorVersion).$(var.MinorVersion).$(var.PatchVersion)"?>
</Include>

 安裝包腳本文件 Product.wsx

基本上分為5個部分:update,condition和action,UI sequence,directory structure及需要安裝的feature.

<?xml version="1.0" encoding="UTF-8"?>
<!-- Add xmlns:util namespace definition to be able to use stuff from WixUtilExtension dll-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
  <!-- This is how we include wxi files -->
  <?include "..\Includes\ScanAppVariables.wxi" ?>
  <!-- 
  Id="*" is to enable upgrading. * means that the product ID will be autogenerated on each build. 
  Name is made of localized product name and version number.
  -->
  <Product Id="*" Name="!(loc.ProductName) $(var.VersionNumber)" Language="!(loc.LANG)" Version="$(var.VersionNumber)" Manufacturer="!(loc.ManufacturerName)" UpgradeCode="$(var.UpgradeCode)">
    <!-- Define the minimum supported installer version (3.0) and that the install should be done for the whole machine not just the current user -->
    <Package InstallerVersion="300" Compressed="yes" InstallScope="perMachine"/>
    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />    
    <!-- Upgrade settings. This will be explained in more detail in a future post -->
    <Upgrade Id="$(var.UpgradeCode)">
      <UpgradeVersion OnlyDetect="yes" Minimum="$(var.VersionNumber)" IncludeMinimum="no" Property="NEWER_VERSION_FOUND" />
      <UpgradeVersion Minimum="0.0.0.0" IncludeMinimum="yes" Maximum="$(var.VersionNumber)" IncludeMaximum="no" Property="OLDER_VERSION_FOUND" />
    </Upgrade>    
    <!-- Reference the global NETFRAMEWORK35 property to check if it exists -->
    <PropertyRef Id="NETFRAMEWORK35"/>    
    <!-- 
    Startup conditions that checks if .Net Framework 3.5 is installed or if 
    we're running the OS higher than Windows XP SP2.
    If not the installation is aborted.
    By doing the (Installed OR ...) property means that this condition will only 
    be evaluated if the app is being installed and not on uninstall or changing
    -->
    <Condition Message="!(loc.DotNetFrameworkNeeded)">
      <![CDATA[Installed OR NETFRAMEWORK35]]>
    </Condition>
    <Condition Message="!(loc.AppNotSupported)">
      <![CDATA[Installed OR ((VersionNT >= 501 AND ServicePackLevel >= 2) OR (VersionNT >= 502))]]>
    </Condition>
    <!-- 
    This custom action in the InstallExecuteSequence is needed to 
    stop silent install (passing /qb to msiexec) from going around it. 
    -->
    <CustomAction Id="NewerVersionFound" Error="!(loc.ScanAppNewerVersionInstalled)" />
    <InstallExecuteSequence>
      <!-- Check for newer versions with FindRelatedProducts and execute the custom action after it -->
      <Custom Action="NewerVersionFound" After="FindRelatedProducts">
        <![CDATA[NEWER_VERSION_FOUND]]>
      </Custom>
      <!-- Remove the previous versions of the product -->
      <RemoveExistingProducts After="InstallInitialize"/>
      <!-- WixCloseApplications is a built in custom action that uses util:CloseApplication below -->
      <Custom Action="WixCloseApplications" Before="InstallInitialize" />
    </InstallExecuteSequence>
    <!-- This will ask the user to close the SuperForm app if it's running while upgrading -->
    <util:CloseApplication Id="CloseSuperForm" CloseMessage="no" Description="!(loc.MustCloseSuperForm)" 
                           ElevatedCloseMessage="no" RebootPrompt="no" Target="$(var.ExeProcessName)" />
    <!-- Use the built in WixUI_InstallDir GUI -->
    <UIRef Id="WixUI_InstallDir" />
    <UI>
      <!-- These dialog references are needed for CloseApplication above to work correctly -->
      <DialogRef Id="FilesInUse" />
      <DialogRef Id="MsiRMFilesInUse" />      
      <!-- Here we'll add the GUI logic for installation and updating in a future post-->      
    </UI>
    <!-- Set the icon to show next to the program name in Add/Remove programs -->
    <Icon Id="ScanAppIcon.ico" SourceFile="..\resources\device.ico" />
    <Property Id="ARPPRODUCTICON" Value="ScanAppIcon.ico" />
    <!-- Installer UI custom pictures. File names are made up. Add path to your pics. –>
    <!--
    <WixVariable Id="WixUIDialogBmp" Value="MyAppLogo.jpg" />
    <WixVariable Id="WixUIBannerBmp" Value="installBanner.jpg" />
    -->
    <!-- the default directory structure -->
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLLOCATION" Name="!(loc.ProductName)" />
      </Directory>
    </Directory>
    <!-- 
    Set the default install location to the value of 
    INSTALLLOCATION (usually c:\Program Files\YourProductName) 
    -->
    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
    <!-- Set the components defined in our fragment files that will be used for our feature  -->
    <Feature Id="ScanAppFeature" Title="!(loc.ProductName)" Level="1">
      <ComponentGroupRef Id="ScanAppFiles" />
      <ComponentRef Id="cmpVersionInRegistry" />
      <ComponentRef Id="cmpIsThisUpdateInRegistry" />

    </Feature>
  </Product>
</Wix>

通過 heat.exe 生成文件或文件夾Fragment

因為項目要安裝的文件比較多,手工輸入到wsx比較麻煩,可以通過heat.exe自動生成componentgourp,然后加入到feature中

"$(WIX)bin\heat.exe" dir "..\Artifact\Main" -cg ScanAppFiles -gg -scom -sreg -sfrag -srd -dr INSTALLLOCATION -var var.FilesDir -out "$(ProjectDir)Fragments\FilesFragment.wxs"

 

  1. dir "..\Artifact\Main":需要安裝的文件所在的目錄
  2. –cg ScanAppFiles : 生成的component group的名字
  3. -dr INSTALLLOCATION: 生成Fragment對應的directory
  4. -var var.FilesDir: 替換生成的Fragment文件中$(SourceDir)字段
  5. -out "$(ProjectDir)Fragments\FilesFragment.wxs":輸出文件路徑

FilesFragment.wxs

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <ComponentGroup Id="ScanAppFiles">
            <ComponentRef Id="cmp5BB40DB822CAA7C5295227894A07502E" />
            <ComponentRef Id="cmpCFD331F5E0E471FC42A1334A1098E144" />
            <ComponentRef Id="cmp4614DD03D8974B7C1FC39E7B82F19574" />
            <ComponentRef Id="cmpDF166522884E2454382277128BD866EC" />
        </ComponentGroup>
    </Fragment>
    <Fragment>
        <DirectoryRef Id="INSTALLLOCATION">
            <Component Id="cmp5BB40DB822CAA7C5295227894A07502E" Guid="{117E3352-2F0C-4E19-AD96-03D354751B8D}">
                <File Id="filDCA561ABF8964292B6BC0D0726E8EFAD" KeyPath="yes" Source="$(var.FilesDir)\ScanApp.exe" />
            </Component>
            <Component Id="cmpCFD331F5E0E471FC42A1334A1098E144" Guid="{369A2347-97DD-45CA-A4D1-62BB706EA329}">
                <File Id="filA9BE65B2AB60F3CE41105364EDE33D27" KeyPath="yes" Source="$(var.FilesDir)\ScanApp.pdb" />
            </Component>
            <Component Id="cmp4614DD03D8974B7C1FC39E7B82F19574" Guid="{3443EBE2-168F-4380-BC41-26D71A0DB1C7}">
                <File Id="fil5102E75B91F3DAFA6F70DA57F4C126ED" KeyPath="yes" Source="$(var.FilesDir)\ScanApp.vshost.exe" />
            </Component>
            <Component Id="cmpDF166522884E2454382277128BD866EC" Guid="{0C0F3D18-56EB-41FE-B0BD-FD2C131572DB}">
                <File Id="filF7CA5083B4997E1DEC435554423E675C" KeyPath="yes" Source="$(var.Files)\ScanApp.vshost.exe.manifest" />
            </Component>
        </DirectoryRef>
    </Fragment>
</Wix>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM