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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (3投票s)

2018 年 3 月 17 日

CPOL

3分钟阅读

viewsIcon

13893

学习使用自定义操作,使 Wix# 更加灵活。

引言

在第 3 部分中,我们的安装程序变得更加复杂。在第 2 部分中确保 .Net 4.7 已安装后,我们将通过利用自定义操作来编写 Apache Tomcat 作为 Windows 服务的安装脚本。

本系列文章的组成部分是

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

背景

WiX 允许 MSI 和 EXE 安装程序执行的操作不仅仅是运行可执行文件和复制文件。 CustomAction 允许您编写各种形式的操作,这些操作可用于诸如在升级期间备份和恢复应用程序设置、设置先决条件或向远程服务器报告安装等操作。

假设

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

  1. WiX Toolset 已安装
  2. 您正在使用 C# 编码(VB.NET 将具有类似的原理,但需要进行一些翻译)
  3. 您已经阅读了第 2 部分。如果我们即将使用的某个操作缺少所需的运行时,则会失败。

入门

在这种情况下,我们需要从 MSI 而不是引导程序中为我们的应用程序安装一个先决条件,例如 Apache Tomcat。这与使用 单独的安装程序不同,就像我们从引导程序中使用它一样。

private static string BuildMsi()
{
    var TestDir = new Dir(@"%ProgramFiles%\My Company\My Product");

    TestDir.Files = System.IO.Directory.GetFiles(@"D:\Checkouts\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);

    project.GUID = new Guid("6fe30b47-2577-43ad-9095-1861ba25889b");
    //project.SourceBaseDir = "<input dir path>";
    //project.OutDir = "<output dir path>";

    project.Actions = new WixSharp.Action[] {          
        new ElevatedManagedAction(CustomActions.CheckForApache, "%this%"),
    };

    return project.BuildMsi();
}

请注意,上面我们向代码添加了一个新 Section。 project.Action 添加了一个操作列表,可以通过多种方式定义。 WiX 的方式主要是 vbs 或 Jscript,但对于 .NET 开发人员来说,Managed Actions 会感觉更熟悉并且更容易维护。 我们已经在下面的单独类中定义了这些操作。

public class CustomActions
{
    [CustomAction]
    public static ActionResult CheckForApache(Session session)
    {
        //check for apache
        return ActionResult.Success;
    }
}

CustomAction 属性将这些方法标记为安装程序的入口点。  但这不是 WiX/Wix# 的功能,因此您需要在文件顶部添加一个 using 语句。

using Microsoft.Deployment.WindowsInstaller;

实施自定义操作

以下是有关如何选择实现自定义操作(例如上面显示的自定义操作)的代码示例。

检查 Apache

public class CustomActions
    {
        [CustomAction]
        public static ActionResult CheckForApache(Session session)
        {
            ActionResult result = ActionResult.Success;
            try
            {
                System.ServiceProcess.ServiceController apache = ServiceController.GetServices()
                    .FirstOrDefault(s => s.ServiceName == "Tomcat8");

                if (apache == null)
                {
                    if (System.IO.File.Exists(@"C:\ProgramData\chocolatey\choco.exe"))
                    {
                        CmdRunner(@"@"" % SystemRoot %\System32\WindowsPowerShell\v1.0\powershell.exe"" - NoProfile - InputFormat None - ExecutionPolicy Bypass - Command ""iex((New - Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"" && SET ""PATH =% PATH %;% ALLUSERSPROFILE %\chocolatey\bin");
                    }

                    CmdRunner("Choco install Tomcat");
                }
            }
            catch
            {
                result = ActionResult.Failure;
            }

            return result;
        }

        public static void CmdRunner(string cmd)
        {
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.FileName = "cmd.exe";
            startInfo.Arguments = @"/C" + cmd ;
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo = startInfo;
            process.Start();
            process.WaitForExit();
        }
    }

上面的代码存在一些问题。我们正在强制我们的用户安装 Chocolatey (Windows 的软件包管理器),我们正在检查默认服务名称,并且我们正在安装一个作为安装程序提供的先决条件(此处)。这意味着我们应该将其捆绑在引导程序中。 

 

关注点

  • Wix# 自定义操作具有多种风格,如 github 上所示,但对于 .NET 开发人员来说,ManagedAction ElevatedManagedAction 更容易处理。
  • 自定义操作仅可在 MSI 中使用,而不能在引导程序中使用。
  • WiX Toolset 文档中有关 CustomAction 元素的说明 详细介绍了许多选项,例如 Return Execute

自定义自定义操作

自定义操作可以不仅仅是我们上面展示的内容。 例如,如果您想在安装后立即启动应用程序怎么办?

new InstalledFileAction("sample_exe", "", Return.asyncNoWait, When.After, Step.InstallFinalize, Condition.NOT_Installed),

这表明此 MSI 安装的文件将在 InstallFinalizes 之后运行,即使在安装程序退出后也会继续运行,但前提是尚未安装该应用程序。

有助于决定何时和什么的关键要素是

  • Return 告诉 MSI 是否需要处理操作完成,如果是,则如何处理。
  • Execute 确定何时计划执行 CustomAction,例如在失败的 MSI 回滚时。
  • WhenStep 结合使用表示与应执行步骤的时间的关系。

处理错误

请务必将您的 CustomActions 适当地包装在 try/catch 中,并妥善处理错误。 可能需要将错误通知给用户,如果由于异常而未执行 MSI 的重要部分,您将希望使该操作失败。 用于通知用户的选项可能包括弹出错误和/或事件日志消息。

历史

  • 2018 年 3 月 16 日:首次发布
© . All rights reserved.