繁体   English   中英

订阅 powershell 在 c# 中的进度不起作用

[英]Subscribing to powershell progress in c# not working

I'm writing a C# GUI program that uses System.Management.Automation to execute powershell commands on an instance created at runtime, I need it to be a persistent powershell instance so I can send multiple commands and collect the output at runtime. 这按预期工作,但我在订阅进度事件时遇到了一些问题。 它仅在我输入错误命令并写入进度已完成 -1% 时触发。

当我输入正确的命令时,它根本不会触发。 错误和 output 事件正常工作,所以我不确定出了什么问题。

我发现另外两个有类似的问题,但他们的解决方案对我不起作用,我将它们链接在下面。 到目前为止,这是我使用失败的代码。

 public class CodeHandler {
   public static PowerShell psInstance;

   public void init() {
     //Create powershell instance
     psInstance = PowerShell.Create();
   }

   public async Task < string > ExecutePowershellCommand(string script) {
     psInstance.AddScript(script);
     psInstance.AddCommand("Out-String");

     PSDataCollection < PSObject > outputCollection = new PSDataCollection < PSObject > ();
     outputCollection.DataAdded += outputCollection_DataAdded;

     //The Part I Can't Get To Work
     psInstance.Streams.Progress.DataAdded += (sender, eventargs) => {
       PSDataCollection < ProgressRecord > progressRecords = (PSDataCollection < ProgressRecord > ) sender;
       Console.WriteLine("!Progress is {0} percent complete", progressRecords[eventargs.Index].PercentComplete);
     };

     psInstance.Streams.Error.DataAdded += Error_DataAdded;

     IAsyncResult result = psInstance.BeginInvoke < PSObject, PSObject > (null, outputCollection);

     while (!result.IsCompleted) {
       Console.WriteLine("Waiting for pipeline to finish...");
       await Task.Delay(100);
     }

     PSInvocationState state = psInstance.InvocationStateInfo.State;
     Console.WriteLine("Execution has stopped. The pipeline state: " + state);
     if (state != PSInvocationState.Completed)
       return string.Empty;

     StringBuilder stringBuilder = new StringBuilder();
     foreach(PSObject outputItem in outputCollection) {
       stringBuilder.AppendLine(outputItem.BaseObject.ToString());
       Console.WriteLine(outputItem.BaseObject.ToString());
     }

     return stringBuilder.ToString();
   }

 }

参考:

从 C# 中获取 Write-Progress -PercentComplete 状态

在 C# 中读取 Powershell 进度条 Output

添加psInstance.EndInvoke(result); 如下所示:

                       ...
 IAsyncResult result = psInstance.BeginInvoke < PSObject, PSObject > (null, outputCollection);

 while (!result.IsCompleted) {
   Console.WriteLine("Waiting for pipeline to finish...");
   await Task.Delay(100);
 }

 psInstance.EndInvoke(result);

                       ...

您的脚本需要使用Write-Progress

示例脚本

# Use Get-Command to get list of commands and store them in the $cmds variable.
$cmds = Get-Command

# Pipe the events to the ForEach-Object cmdlet.
$cmds  | ForEach-Object -Begin {
    # In the Begin block, use Clear-Host to clear the screen.
    Clear-Host

    # Set the $i counter variable to zero.
    $i = 0

    # Set the $out variable to a empty string.
    $out = ""
} -Process {
    # get name
     # Append to the out variable.
     # $out=$out + $_

     write-output ($_.Name + " " + $_.Version) 

    # Increment the $i counter variable which is used to create the progress bar.
    $i = $i+1

    # Use Write-Progress to output a progress bar.
    # The Activity and Status parameters create the first and second lines of the progress bar heading, respectively.
    Write-Progress -Activity "Searching Commands" -Status "Progress:" -PercentComplete ($i/$cmds.count*100)
} -End {
    # Display using the out variable.
    # $out
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM