65.9K
CodeProject 正在变化。 阅读更多。
Home

创建包含先决条件的 Wix# 安装程序 - 第一部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (13投票s)

2018年2月25日

CPOL

2分钟阅读

viewsIcon

43674

学习如何使用 Wix# 为您的应用程序创建安装程序,该安装程序捆绑了多个 MSI、运行时和其他依赖项

引言

在第一部分中,我们将研究如何从控制台应用程序到 MSI,使用 Wix#,并使程序能够安装和升级/卸载。

本系列文章的组成部分是

  1. 使用 Wix# 创建 MSI 安装程序(本篇)
  2. 创建捆绑先决条件的 EXE 安装程序
  3. 创建自定义操作以简化任务

背景

Wix# (GitHub) 是一种以编程方式创建 Windows 安装程序的方法,它利用了 WiX 工具集 的强大功能和灵活性。 我发现这是使安装程序可编辑且易于一组开发人员维护的最简单方法,他们对 WiX 工具集本身了解甚少。 Wix# 相对于原始 WiX 的主要优势在于其易用性。 您不必是 WiX 工具集专家才能有效地使用 Wix#。

假设

我将假设以下几点。 如果这些不正确,您的体验可能会有所不同。

  1. Visual Studio 2017 是您的 IDE
  2. WiX 工具集 已安装
  3. 您正在使用 C# 编码(VB.NET 将具有类似的原理,但需要进行一些翻译)
  4. 您正在使用 Visual Studio 的 WixSharp 项目模板扩展

入门

using System;
using WixSharp;
 
class Script
{
    static public void Main(string[] args)
    {
        var project = new Project("MyProduct",
                          new Dir(@"%ProgramFiles%\My Company\My Product",
                              new File(@"Files\Docs\Manual.txt"),
                              new File(@"Files\Bin\MyApp.exe")));
 
        project.GUID = new Guid("6f330b47-2577-43ad-9095-1861ba25889b");
 
        Compiler.BuildMsi(project);
    }
}

如您所见,Project 获取一个名称,然后定义一个目录以及应复制哪些文件到其中。 然后添加一个 GUID(您需要替换此 GUID)。 最后,它构建 MSI。 现在构建此项目会将一个“wix”文件夹添加到我们的项目中,并将生成的 WiX 文件转储到其中。

<?xml version="1.0" encoding="utf-8"?>
<!--
<auto-generated>
    This code was generated by WixSharp.
    Changes to this file will be lost if the code is regenerated.
</auto-generated>
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product Id="6fe30b47-2577-43ad-9095-1861ca25889c" Name="MyProduct" 
   Language="1033" Codepage="Windows-1252" Version="1.0.0.0" 
   UpgradeCode="6fe30b47-2577-43ad-9095-1861ba25889b" Manufacturer="ccarter">
    <Package InstallerVersion="200" Compressed="yes" 
    SummaryCodepage="Windows-1252" Languages="1033" />
    <Media Id="1" Cabinet="MyProduct.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder" Name="ProgramFilesFolder">
        <Directory Id="ProgramFilesFolder.My_Company" Name="My Company">
          <Directory Id="INSTALLDIR" Name="My Product">

            <Component Id="Component.Program.cs_2096188551" 
            Guid="6fe30b47-2577-43ad-9095-1861e8d77bb1">
              <File Id="Program.cs_2096188551" Source="Program.cs" />
            </Component>

          </Directory>
        </Directory>
      </Directory>
    </Directory>

    <UIRef Id="WixUI_Minimal" />
    <UIRef Id="WixUI_ErrorProgressText" />

    <Feature Id="Complete" Title="Complete" Absent="allow" Level="1">
      <ComponentRef Id="Component.Program.cs_2096188551" />
    </Feature>

  </Product>
</Wix>

我们还发现“MyProduct.msi”输出到项目目录。

因此,除了 Wix# 示例更简洁之外,我们为什么更喜欢 Wix# 而不是原始 Wix? 好吧..

var TestDir = new Dir(@"%ProgramFiles%\My Company\My Product");

TestDir.Files = System.IO.Directory.GetFiles
(@"\path\to\solution\WixSharp Tutorial\WixSharp Tutorial\SampleApp\bin\Release").Where
(file => file.EndsWith(".dll") || 
file.EndsWith(".exe")).Select(file => new File(file)).ToArray();

var project = new Project("MyProduct", TestDir);

这会产生以下结果

<?xml version="1.0" encoding="utf-8"?>
<!--
<auto-generated>
    This code was generated by WixSharp.
    Changes to this file will be lost if the code is regenerated.
</auto-generated>
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product Id="6fe30b47-2577-43ad-9095-1861ca25889c" Name="MyProduct" 
   Language="1033" Codepage="Windows-1252" Version="1.0.0.0" 
   UpgradeCode="6fe30b47-2577-43ad-9095-1861ba25889b" Manufacturer="ccarter">
    <Package InstallerVersion="200" Compressed="yes" 
    SummaryCodepage="Windows-1252" Languages="1033" />
    <Media Id="1" Cabinet="MyProduct.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="INSTALLDIR" Name="ProgramFilesFolder">

        <Component Id="Component.Editor.dll_374746071" 
        Guid="6fe30b47-2577-43ad-9095-18613d90149a">
          <File Id="Editor.dll_374746071" 
          Source="..\SampleApp\bin\Release\Editor.dll" />
        </Component>

        <Component Id="Component.SampleApp.dll_1981177689" 
        Guid="6fe30b47-2577-43ad-9095-1861c6f85d24">
          <File Id="SampleApp.dll_1981177689" 
          Source="..\SampleApp\bin\Release\SampleApp.dll" />
        </Component>

        <Component Id="Component.SampleApp.exe_60174109" 
        Guid="6fe30b47-2577-43ad-9095-1861a74d0c84">
          <File Id="SampleApp.exe_60174109" 
          Source="..\SampleApp\bin\Release\SampleApp.exe" />
        </Component>

        <Component Id="Component.SampleAppEditor.exe_729600358" 
         Guid="6fe30b47-2577-43ad-9095-18610c59b6e9">
          <File Id="SampleAppEditor.exe_729600358" 
           Source="..\SampleApp\bin\Release\SampleAppEditor.exe" />
        </Component>

        <Component Id="Component.Sugar.dll_2062009301" 
        Guid="6fe30b47-2577-43ad-9095-18616d4e4353">
          <File Id="Sugar.dll_2062009301" 
          Source="..\SampleApp\bin\Release\Sugar.dll" />
        </Component>

        <Component Id="Component.SugarShaker.exe_1177907971" 
         Guid="6fe30b47-2577-43ad-9095-1861746701f0">
          <File Id="SugarShaker.exe_1177907971" 
          Source="..\SampleApp\bin\Release\SugarShaker.exe" />
        </Component>

        <Directory Id="INSTALLDIR.My_Company" Name="My Company">
          <Directory Id="INSTALLDIR.My_Company.My_Product" Name="My Product">

            <Component Id="My_Product.EmptyDirectory" 
             Guid="6fe30b47-2577-43ad-9095-18611cb1741a" KeyPath="yes">
              <CreateFolder />
              <RemoveFolder Id="INSTALLDIR.My_Company.My_Product" On="uninstall" />
            </Component>

          </Directory>

          <Component Id="INSTALLDIR.My_Company" 
           Guid="6fe30b47-2577-43ad-9095-18618b356f3d" KeyPath="yes">
            <CreateFolder />
            <RemoveFolder Id="INSTALLDIR.My_Company" On="uninstall" />
          </Component>

        </Directory>
      </Directory>

      <Component Id="TARGETDIR" 
      Guid="6fe30b47-2577-43ad-9095-18612df5f80e" KeyPath="yes">
        <CreateFolder />
        <RemoveFolder Id="TARGETDIR" On="uninstall" />
      </Component>

    </Directory>

    <UIRef Id="WixUI_Minimal" />
    <UIRef Id="WixUI_ErrorProgressText" />

    <Feature Id="Complete" Title="Complete" Absent="allow" Level="1">
      <ComponentRef Id="Component.Editor.dll_374746071" />
      <ComponentRef Id="Component.SampleApp.dll_1981177689" />
      <ComponentRef Id="Component.SampleApp.exe_60174109" />
      <ComponentRef Id="Component.SampleAppEditor.exe_729600358" />
      <ComponentRef Id="Component.Sugar.dll_2062009301" />
      <ComponentRef Id="Component.SugarShaker.exe_1177907971" />
      <ComponentRef Id="My_Product.EmptyDirectory" />
      <ComponentRef Id="INSTALLDIR.My_Company" />
      <ComponentRef Id="TARGETDIR" />
    </Feature>

  </Product>
</Wix>

使用 linq,我们可以创建更易于 C# 和 Linq 熟悉的人理解的复杂规则集。 WiX 实现这种方法不需要在 WiX 文件中为每个文件条目,但也会失去一些功能,因为我们可以像我们喜欢的那样评估文件。

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" 
 xmlns:fg="http://www.firegiant.com/schemas/v3/wxs/fgwep.xsd"> 
 <Fragment> 
  <ComponentGroup Id="ContentComponents"> 
   <Component Directory="ContentFolder"> 
    <fg:HarvestFolder Source="path\to\content\*.dll" /> 
   </Component> 
   <Component Directory="ContentFolder">
    <fg:HarvestFolder Source="path\to\content\*.exe" />
   </Component> 
  </ComponentGroup> 
 </Fragment> 
</Wix>

在本系列文章的第二部分中,我们将研究将多个项目作为单独的 MSI 文件、功能集以及安装先决条件 .NET Framework。

关注点

  • 使用 Wix# 探索更复杂设置通常需要参考 Wix 教程和示例,然后查找 Wix# 中的等效项。
  • Wix# Github 仓库拥有大量的示例项目,这些项目非常有用。

处理错误

如果在构建时遇到错误,如下所示

Severity    Code    Description    Project    File    Line    Suppression State
Error        The command ""Path\to\Project\WixSharp Setup\bin\Debug\WixSharp Setup.exe" 
"/MSBUILD:WixSharp Setup"" exited with code -532459699.

调试“Path\to\Project\WixSharp Setup\bin\Debug\WixSharp Setup.exe” "/MSBUILD:WixSharp Setup"。 在我的例子中,最终原因是它正在寻找一个不存在的目录,以从中提取用于 MSI 的文件。

历史

  • 2018年2月24日:首次发布
© . All rights reserved.