首页 > 解决方案 > 在 Windows 8.1 上使用 task.run 安装巧克力文件的问题

问题描述

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

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

有谁知道 Windows 8.1 上的巧克力或任务是否有任何问题?

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 的虚拟机以继续尝试调试自己。欢迎任何其他建议。

标签: c#.nettaskwindows-8.1chocolatey

解决方案


不幸的是,我无法确保我的建议是正确的。主要原因是,我无法弄清楚PowerShellAction应该是什么。我假设这里PowerShellSystem.Management.Automation.PowerShell.

我建议几件事:

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

代码(untestet)可能是这样的:

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它是为了能够对原始任务中可能发生的任何异常做出反应。

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


推荐阅读