【问题标题】:Check if .NETCore is installed using CustomAction with Wix检查是否使用带有 Wix 的自定义操作安装了 .NET Core
【发布时间】:2019-11-19 08:57:31
【问题描述】:

如果未安装 NetCore 3.1(预览版),我想取消安装

我创建了这个 CustomAction:

using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Win32;

namespace WixCustomAction
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult CheckDotNetCore31Installed(Session session)
        {
            session.Log("Begin CheckDotNetCore31Installed");

            RegistryKey lKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost");

            var version = (string)lKey.GetValue("Version");

            session["DOTNETCORE31"] = version == "3.1.0-preview3.19553.2" ? "1" : "0";

            return ActionResult.Success;
        }
    }
}

然后在 WXS 文件中:

<<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">

   <Product ...>

  (...)

    <Property Id="DOTNETCORE31">0</Property>

    <Condition Message="You must first install the .NET Core 3.1 Runtime">
      Installed OR DOTNETCORE31="1"
    </Condition>

    <InstallExecuteSequence>
      <Custom Action="Check.NetCore" Before="LaunchConditions">NOT Installed</Custom>
    </InstallExecuteSequence>

  </Product>

  <Fragment>
    <Binary Id="WixCA.dll" SourceFile="$(var.WixCustomAction.TargetDir)$(var.WixCustomAction.TargetName).CA.dll" />
    <CustomAction Id="Check.NetCore" BinaryKey="WixCA.dll" DllEntry="CheckDotNetCore31Installed" Execute="immediate"  />
  </Fragment>

这就是我遇到问题的地方,因为我总是收到警告消息。 一个主意 ?谢谢

【问题讨论】:

  • 请添加警告信息。
  • 对我来说是“”这一行。如果你问这个问题,就说明我什么都不懂:(
  • 测试值不会是&lt;![CDATA[Installed OR (DOTNETCORE31 = 1)]]&gt;
  • 语法似乎更正确,但对于这个问题,结果不会改变:/

标签: c# .net-core installation wix custom-action


【解决方案1】:

也许使用 cmd 检查 .net 核心版本会更好 dotnet --version命令,避免windows架构依赖

此案例的自定义操作示例:

    [CustomAction]
    public static ActionResult CheckVersion(Session session)
    {
       var minVersion = new Version(3, 1, 1);
        var command = "/c dotnet --version";// /c is important here
        var output = string.Empty;
        using (var p = new Process())
        {
            p.StartInfo = new ProcessStartInfo()
            {
                FileName = "cmd.exe",
                Arguments = command,
                UseShellExecute = false,                    
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                CreateNoWindow = true,
            };
            p.Start();
            while (!p.StandardOutput.EndOfStream)
            {
                output += $"{p.StandardOutput.ReadLine()}{Environment.NewLine}";
            }
            p.WaitForExit();
            if (p.ExitCode != 0)
            {
                session["DOTNETCORE1"] = "0";
                return ActionResult.Success;
                //throw new Exception($"{p.ExitCode}:{ p.StandardError.ReadToEnd()}");
            }

            //you can implement here your own comparing algorithm
            //mine will not work with -perview string, but in this case you can just 
            //replace all alphabetical symbols with . using regex, for example
            var currentVersion = Version.Parse(output);
            session["DOTNETCORE1"] = (currentVersion < minVersion) ? "0" : "1";
            
            return ActionResult.Success;
         }
      

更新: 正如亚当所提到的,我对那个 sn-p 错了——它只适用于 SDK。 这是另一个获得运行时的方法:

    static readonly List<string> runtimes = new List<string>()
    {
        "Microsoft.NETCore.App",//.NET Runtime
        "Microsoft.AspNetCore.App",//ASP.NET Core Runtime
        "Microsoft.WindowsDesktop.App",//.NET Desktop Runtime
    };

    [CustomAction]
    public static ActionResult CheckVersion(Session session)
    {
        var minVersion = new Version(3, 1, 1);
        var command = "/c dotnet --list-runtimes";// /c is important here
        var output = string.Empty;
        using (var p = new Process())
        {
            p.StartInfo = new ProcessStartInfo()
            {
                FileName = "cmd.exe",
                Arguments = command,
                UseShellExecute = false,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                CreateNoWindow = true,
            };
            p.Start();
            while (!p.StandardOutput.EndOfStream)
            {
                output += $"{p.StandardOutput.ReadLine()}{Environment.NewLine}";
            }
            p.WaitForExit();
            if (p.ExitCode != 0)
            {
                session["DOTNETCORE1"] = "0";
                return ActionResult.Success;
                //throw new Exception($"{p.ExitCode}:{ p.StandardError.ReadToEnd()}");
            }
            session["DOTNETCORE1"] = (GetLatestVersionOfRuntime(runtimes[0], output) < minVersion) ? "0" : "1";
            return ActionResult.Success;
        }
    }

    private static Version GetLatestVersionOfRuntime(string runtime, string runtimesList)
    {
        var latestLine = runtimesList.Split(Environment.NewLine).ToList().Where(x => x.Contains(runtime)).OrderBy(x => x).LastOrDefault();
        if (latestLine != null)
        {
            Regex pattern = new Regex(@"\d+(\.\d+)+");
            Match m = pattern.Match(latestLine);
            string versionValue = m.Value;
            if (Version.TryParse(versionValue, out var version))
            {
                return version;
            }
        }
        return null;
    }

【讨论】:

  • 总的来说,我喜欢这个想法,但 dotnet --version 不适用于 .NET Core 运行时,仅适用于 SDK。运行时确实支持dotnet --list-runtimes,但是解析有点繁琐。
  • 是的,你完全正确。那个时候我只在开发者的机器上测试过。更新帖子解析dotnet --list-runtimes
【解决方案2】:

调试:您是否将调试器附加到您的自定义操作,以便您 可以看到那里发生了什么?我敢打赌,它没有正确设置您的财产。 The custom action might not be running at all?显示一个消息框来冒烟测试一下?更多参与(附加 Visual Studio 调试器):

LaunchCondition:在 MSI 数据库中,启动条件由 LaunchCondition table 中的记录表示。该表有两列。 条件列包含一个表达式,该表达式必须评估为 True 才能继续安装

结论So your condition does not evaluate to true properly。是什么 DOTNETCORE31 的实际值?我敢打赌是0。再检查一遍 请。最简单的方法显然是直接将其设置为 1 而不是 0 - 然后再次编译并测试。硬编码暂时这样:

<Property Id="DOTNETCORE31">1</Property>

链接:以下是关于发布条件和其他主题的一些先前答案:


WiX 自定义操作:您有调用自定义操作的基本标记吗?使用 Orca 检查编译的 MSI 以查看 BinaryCustomActionInstallExecuteSequenceInstallUISequence 表中是否有条目。一些模拟 WiX 标记 (pillage gihub.com for samples?):

<Binary Id="CustomActions" SourceFile="C:\Test.CA.dll" />

<...>

<CustomAction Id="CustomAction1" BinaryKey="CustomActions" DllEntry="CustomAction1"/>

<...>

<InstallUISequence>
  <Custom Action="CustomAction1" After="CostFinalize" />
</InstallUISequence>

<...>

<InstallExecuteSequence>
  <Custom Action="CustomAction1" After="CostFinalize" />
</InstallExecuteSequence>

GUI 和静默安装:显然,您也可以从对话框事件中运行自定义操作(例如单击按钮),但这会使其无法在静默模式下运行. GUI 在静默模式下被跳过,因此您需要在 InstallExecuteSequence 以及 GUI 中运行自定义操作。

【讨论】:

  • 非常感谢您提供的信息丰富的信息。这对我帮助很大。我能够调试我的 CustomAction 并了解问题出在哪里:它没有读取 64 位注册表!
  • 啊,经典的位数问题。总是名列前茅,我应该提到它。我不确定此注册表读取是否是检测 .NET Core 的最佳方法,但这是另一回事。下一个版本什么时候出现?以后可能会看看。有内置的措施来检测主要的 .NET 框架(老派 .NET)。
  • 我在等待github.com/wixtoolset/issues/issues/6099,但我们必须等待 .NETCore 退出预览版
  • 啊,说明我已经过时了。感谢您的链接!也许您可以进行“高于”检查,而不仅仅是检查特定的版本号?我没学过这么多。
  • 好主意!一旦有新的预览版可用,我将检查版本号如何演变
【解决方案3】:

Stein Asmul 的帮助下,我能够调试我的CustomAction。这是有效的代码:

using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Win32;

namespace WixCustomAction
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult CheckDotNetCore31Installed(Session session)
        {
            session.Log("Begin CheckDotNetCore31Installed");

            RegistryKey localMachine64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
            RegistryKey lKey = localMachine64.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost\", false);

            var version = (string)lKey.GetValue("Version");

            session["DOTNETCORE1"] = version == "3.1.0-preview3.19553.2" ? "1" : "0";

            return ActionResult.Success;
        }
    }
}

【讨论】:

  • 使用SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost时出现问题;如果管理员卸载 .net core,注册表值会保留,并且不会反映实际安装的内容。
猜你喜欢
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 2012-04-30
  • 2016-11-28
  • 1970-01-01
相关资源
最近更新 更多