用Wix製作VSPackage的安裝包

  • 2019 年 10 月 5 日
  • 筆記

做完VSPackage後,如何打包發佈它?其實有很多種打包的方式,在這裡我只介紹在VS2008下用Wix製作VSPackage的安裝程序。您首先要下載並安裝Wix toolset(http://wix.codeplex.com/)。

創建測試用的VSPackage

新建一個VSPackage項目用來測試。為了演示安裝後的效果,別忘了在嚮導中給它添加一個Menu Command。

創建Wix項目

新建一個項目,項目類型選擇Wix-》Wix Project,如下圖:

完成後的解決方案視圖如下:

生成用於註冊VSPackage的wxs文件

VSPackage要想使用,必須往註冊表裡添加一些信息,我們用regpkg這個命令來幫助我們把這些信息生成到一個wxs文件里。

首先編譯我們的Package項目,然後用VS2008 SDK帶的命令行轉到Package的bindebug目錄,並運行下面的語句。

regpkg /wixfile:VSPackage1.wxs /codebase "<full-path>VSPackage1.dll"

其中,<full-path>代表Package程序集所在目錄的全路徑,例如E:VSPackageInstallerVSPackage1bindebug。

這個命令運行成功後,會在相同目錄下生成一個VSPackage1.wxs的文件,我們需要把這個文件添加到VSPackageInstaller項目下面。注意,添加進來之後,這個文件的Build Action默認是編譯(Compile),我們需要把它改成內容(Content),因為這個VSPackage1.wsx文件需要包括在主Product.wsx中,在編譯Product.wsx的時候去編譯它。如下圖:

添加安裝邏輯

首先要給VSPackageInstaller項目添加WixUIExtension.dll的引用,如下圖:

然後修改VSPackageInstaller項目下的Product.wxs為:

<?xml version="1.0" encoding="UTF-8"?><Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">    <Product Id="4981e388-4c5f-4d7d-bc29-11fedb49ebea" Name="VSPackageInstaller" Language="1033" Version="1.0.0.0" Manufacturer="VSPackageInstaller" UpgradeCode="0b0867f6-f86e-4c0a-aa57-ddb1fe4165df">        <Package InstallerVersion="200" Compressed="yes" />         <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />     <!--取出VS2008的devenv.exe路徑-->    <Property Id="DEVENV_EXE_PATH">      <RegistrySearch Id="RegSearch_DevenvExe_Path" Root="HKLM" Key="SOFTWAREMicrosoftVisualStudio9.0SetupVS" Name="EnvironmentPath" Type="raw" />    </Property>            <Directory Id="TARGETDIR" Name="SourceDir">            <Directory Id="ProgramFilesFolder">                <Directory Id="INSTALLLOCATION" Name="VSPackageInstaller">                     <Component Id="ProductComponent" Guid="42a95449-0cc2-4045-a9e1-b2f4296a376a">             <!--複製程序集-->             <File Id="VSPackage1"                   Source="$(var.SolutionDir)VSPackage1bindebugVSPackage1.dll" />             <!--把註冊表信息包括進來-->             <?include VSPackage1.wxs ?>                     </Component>                 </Directory>            </Directory>        </Directory>         <Feature Id="ProductFeature" Title="VSPackageInstaller" Level="1">             <ComponentRef Id="ProductComponent" />         </Feature>     <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />    <UI>      <UIRef Id="WixUI_InstallDir" />          </UI>    <InstallExecuteSequence>      <Custom Action="CA_DeployPackage" Before="InstallFinalize" />    </InstallExecuteSequence>     <!--執行devenv /setup /nosetupvstemplates,把我們的Package安裝到vs2008里-->    <CustomAction Id="CA_DeployPackage" Property="DEVENV_EXE_PATH" ExeCommand="/setup /nosetupvstemplates" Impersonate="no" Execute="deferred" />   </Product></Wix>

和修改前相比,我們主要在Product.wxs里增加了如下內容:

  1. 搜索註冊表,取出vs2008的devenv.exe程序的路徑
  2. 把VSPackage.dll複製到目標目錄
  3. 把註冊表信息(VSPackage1.wxs)包括進來
  4. 運行devenv.exe /setup /nosetupvstemplates(由於我們的測試Package沒有VSTemplate,所以加上了/nosetupvstemplates參數以提高速度)

修改完Product.wxs之後,我們還需要修改一下VSPackage1.wxs文件的下面這一行:

<Registry Name="CodeBase" Value="[#File_VSPackage1.dll]" Type="string" />

修改為:

<Registry Name="CodeBase" Value="[#VSPackage1]" Type="string" />

也就是把CodeBase的Value改為

<File Id="VSPackage1" Source="$(var.SolutionDir)VSPackage1bindebugVSPackage1.dll" />

中Id對應的值。

測試安裝包

到此為止,我們的安裝包已經可以用了,編譯VSPackageInstaller項目,並運行VSPackageInstaller.msi,可以看到安裝界面已經出來了。

安裝成功之後,重啟VS,點擊工具菜單,可以看到我們的Package已經被安裝進去了:

重新運行這個安裝程序可以卸載掉我們的Package。

改進安裝包

雖然我們的安裝包已經可以用了,但還存在幾個問題:

  1. 它是英文的
  2. 如果用戶沒裝VS2008,安裝程序會報錯
  3. 安裝時,不想出現license對話框
  4. 執行devenv.exe /setup /nosetupvstemplates時耗費的時間比較久,但安裝程序沒有任何提示

要想變成中文,需要下載中文的wxl文件,並作為嵌入的資源把它添加到VSPackageInstaller項目中。然後修改Product.wxs文件,把Product節點的Language從1033改為2052,並添加一個CodePage=「936」的屬性。然後修改VSPackageInstaller的項目屬性,在Build頁簽里,把「Cultures to build」改為zh-cn,如下圖:

再重新編譯VSPackageInstaller項目,會在bindebugzh-cn目錄下找到新編譯出來的msi。

如果想去掉安裝時的license對話框,需要在Product.wsx的UI節點下增加下面的內容:

<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2">1</Publish><Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">1</Publish>

如果想在執行devenv.exe /setup /nosetupvstemplates時安裝程序給出提示信息,需要在UI節點下指定ProgressText:

<ProgressText Action="CA_DeployPackage">  正在配置Visual Studio 2008...(請稍等幾分鐘)</ProgressText>

如果想在安裝時先判斷客戶端有沒有安裝VS2008,需要指定Condition,如:

<Condition Message="[ProductName] 必須運行在Visual Studio 2008里,所以請先安裝Visual Studio 2008。">DEVENV_EXE_PATH</Condition>

這裡的DEVENV_EXE_PATH是我們在上面搜索出來的devenv.exe的路徑,這裡通過判斷這個路徑是否為空來確定是否安裝了VS2008。

最終的Product.wsx內容如下:

<?xml version="1.0" encoding="UTF-8"?><Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">    <Product Id="4981e388-4c5f-4d7d-bc29-11fedb49ebea" Name="VSPackage1" Language="2052" Codepage="936" Version="1.0.0.0" Manufacturer="VSPackage1" UpgradeCode="0b0867f6-f86e-4c0a-aa57-ddb1fe4165df">        <Package InstallerVersion="200" Compressed="yes" />         <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />     <!--取出VS2008的devenv.exe路徑-->    <Property Id="DEVENV_EXE_PATH">      <RegistrySearch Id="RegSearch_DevenvExe_Path" Root="HKLM" Key="SOFTWAREMicrosoftVisualStudio9.0SetupVS" Name="EnvironmentPath" Type="raw" />    </Property>    <!-- Launch conditions -->    <Condition Message="必須以管理員身份運行 [ProductName]安裝程序。">Privileged</Condition>    <Condition Message="[ProductName] 必須運行在Visual Studio 2008里,所以請先安裝Visual Studio 2008。">DEVENV_EXE_PATH</Condition>            <Directory Id="TARGETDIR" Name="SourceDir">            <Directory Id="ProgramFilesFolder">                <Directory Id="INSTALLLOCATION" Name="VSPackageInstaller">                     <Component Id="ProductComponent" Guid="42a95449-0cc2-4045-a9e1-b2f4296a376a">             <!--複製程序集-->             <File Id="VSPackage1"                   Source="$(var.SolutionDir)VSPackage1bindebugVSPackage1.dll" />             <!--把註冊表信息包括進來-->             <?include VSPackage1.wxs ?>                     </Component>                 </Directory>            </Directory>        </Directory>         <Feature Id="ProductFeature" Title="VSPackageInstaller" Level="1">             <ComponentRef Id="ProductComponent" />         </Feature>     <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />    <UI>      <UIRef Id="WixUI_InstallDir" />      <!-- skip licence dialog -->      <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2">1</Publish>      <Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">1</Publish>      <ProgressText Action="CA_DeployPackage">        正在配置Visual Studio 2008...(請稍等幾分鐘)      </ProgressText>    </UI>    <InstallExecuteSequence>      <Custom Action="CA_DeployPackage" Before="InstallFinalize" />    </InstallExecuteSequence>     <!--執行devenv /setup /nosetupvstemplates,把我們的Package安裝到vs2008里-->    <CustomAction Id="CA_DeployPackage" Property="DEVENV_EXE_PATH" ExeCommand="/setup /nosetupvstemplates" Impersonate="no" Execute="deferred" />   </Product></Wix>

最終的效果如下: