在 windows 8.1 上使用 task.run 安装巧克力文件时出现问题

Problem with installing chocolatey files with task.run on windows 8.1

我的任务是创建一个工具来帮助轻松设置客户系统。我创建了一个通过 c# 中的 powershell 调用巧克力脚本的函数,我使用 Task.run 创建一个新线程,因此它不会影响 UI 线程,系统工作正常,但我'我在使用某些计算机时遇到问题。我无法访问这些计算机并且对他们的系统了解不多,并且由于时间限制无法访问这些计算机,这无济于事。我知道他们有 windows 8.1。我得到了一个 windows 10 虚拟机进行测试(我仍然不明白,因为众所周知这是一个 windows 8 问题)

这是代码。 我知道一个事实(由于有一次我被授予访问这些计算机的权限)它在 Task.Run(() => task)

上停止

有谁知道 windows 8.1 上的 chocolatey 或 Tasks 是否有任何问题?

Task callTask = Task.Run(() => ExecuteAsynchronouslyAsync("chocolatey string", CheckBox box, string logName));

public async Task<PowerShellAction> ExecuteAsynchronouslyAsync(String commandStr, CheckBox box, string logName)
{
    powerShellAction = new PowerShellAction();
    powerShellAction.isFinished = false;
    using (PowerShell ps = PowerShell.Create())
    {
        ps.AddScript(commandStr); // adding the script to the powershell script.
        outputCollection = new PSDataCollection<PSObject>();
        outputCollection.DataAdded += OutputData;
        IAsyncResult result = ps.BeginInvoke<PSObject, PSObject>(null, outputCollection);
        PSDataCollection<PSObject> execRes = await Task.Factory.FromAsync(result, ps.EndInvoke);
    }
    return powerShellAction;
}

现在正在尝试获取 8.1 的虚拟机以继续尝试调试自己。欢迎任何其他建议。

很遗憾,我无法确保我的建议是正确的。主要原因是,我不知道 PowerShellAction 应该是什么。我在这里假设 PowerShellSystem.Management.Automation.PowerShell

我建议几件事:

  1. 您的代码无法编译有几个原因:您的方法的第一行没有 var 或类型声明,并且方法调用不会因为添加 string 而起作用关键词。以后请尽量避免粘贴像您这样的代码,因为重建您的示例非常困难。
  2. 不要将 UI 控件绕过异步方法,而是使用所需的值(例如 box.IsChecked 作为 bool)。
  3. ConfigureAwait(false) 添加到您的 await 以防止 .NET 尝试同步回上下文。
  4. 更加注意您的方法中的异常处理。
  5. 如果您的方法中不需要任何东西,请不要 return。

代码(未测试)可能是这样的:

var task = Task.Run(() => ExecutePowerShellAsync("chocolatey string", box.IsChecked, "NameOfTheLog"));

public async Task<PowerShellAction> ExecutePowerShellAsync(String commandStr, bool checkBoxValue, string logName)
{
    var powerShellAction = new PowerShellAction();
    powerShellAction.isFinished = false;
    using (PowerShell ps = PowerShell.Create())
    {
        ps.AddScript(commandStr); // adding the script to the powershell script.
        var outputCollection = new PSDataCollection<PSObject>();
        outputCollection.DataAdded += OutputData;
        IAsyncResult result = ps.BeginInvoke<PSObject, PSObject>(null, outputCollection);
        PSDataCollection<PSObject> execRes = await Task.Factory.FromAsync(result, ps.EndInvoke).ContinueWith(t => {
            if (t.IsFaulted) 
            {
                System.Diagnostics.Trace.TraceError("Task faulted with exception: " + t.Exception?.Message);    
            }
            return t.Result;
        }).ConfigureAwait(false);
    }
    return powerShellAction;
}

我使用 ContinueWith 是为了能够对原始任务中可能发生的任何异常做出反应。

我建议这样做是因为你的描述闻起来像你有一个典型的线程锁,这意味着简单的代码不会由于异常或上下文同步问题而返回。