C#调用PowerShell脚本未生成文件,如何等待脚本执行完成?
解决C#调用PowerShell的等待执行与输出重定向问题
一、等待PowerShell脚本执行完成
Invoke()默认是同步阻塞方法,会等待脚本执行完毕才返回。你遇到的文件未生成问题,大概率是脚本执行出错、路径解析异常(比如相对路径对应PowerShell工作目录而非C#程序目录)导致的。以下是两种确保脚本执行完成的处理方式:
1. 同步执行并验证状态
执行Invoke()后,通过InvocationStateInfo确认脚本执行状态,避免忽略执行异常:
using System.Management.Automation; using System.Management.Automation.Runspaces; Runspace rs = RunspaceFactory.CreateRunspace(); rs.Open(); PowerShell ps = PowerShell.Create(); ps.Runspace = rs; // 建议使用绝对路径避免工作目录歧义 string filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myfile.txt"); ps.AddScript($"Write-Output Hello | Out-File -FilePath '{filePath}'"); // 同步阻塞执行 var results = ps.Invoke(); // 校验执行状态 if (ps.InvocationStateInfo.State != PSInvocationState.Completed) { throw new InvalidOperationException($"脚本执行失败:{ps.InvocationStateInfo.Reason}"); } rs.Close();
2. 异步执行并等待完成
如果需要异步执行场景,可通过BeginInvoke配合等待句柄实现显式等待:
using System.Management.Automation; using System.Management.Automation.Runspaces; Runspace rs = RunspaceFactory.CreateRunspace(); rs.Open(); PowerShell ps = PowerShell.Create(); ps.Runspace = rs; string filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myfile.txt"); ps.AddScript($"Write-Output Hello | Out-File -FilePath '{filePath}'"); // 异步启动执行 var asyncResult = ps.BeginInvoke(); // 阻塞等待脚本执行完成 asyncResult.AsyncWaitHandle.WaitOne(); // 获取执行结果并清理 var results = ps.EndInvoke(asyncResult); rs.Close();
二、重定向PowerShell的标准输出与错误输出
1. 通过PowerShell Streams捕获输出
C#的PowerShell对象内置Streams属性,可直接获取标准输出、错误输出等流数据:
using System.Management.Automation; using System.Management.Automation.Runspaces; Runspace rs = RunspaceFactory.CreateRunspace(); rs.Open(); PowerShell ps = PowerShell.Create(); ps.Runspace = rs; ps.AddScript("Write-Output 'Hello from stdout'; Write-Error 'Test error message'"); ps.Invoke(); // 读取标准输出 foreach (var item in ps.Streams.Output) { Console.WriteLine($"标准输出:{item.ToString()}"); } // 读取错误输出 foreach (var item in ps.Streams.Error) { Console.WriteLine($"错误输出:{item.ToString()}"); } rs.Close();
2. 在脚本中直接重定向
和PowerShell命令行语法一致,在脚本内用>/>>重定向标准输出,2>重定向错误输出:
ps.AddScript(@" Write-Output 'Hello' > output.txt Write-Error 'Something went wrong' 2> error.log "); ps.Invoke();
3. 使用API链式构建命令(更可控)
避免拼接脚本字符串,通过AddCommand链式调用配置输出重定向:
using System.Management.Automation; using System.Management.Automation.Runspaces; Runspace rs = RunspaceFactory.CreateRunspace(); rs.Open(); PowerShell ps = PowerShell.Create(); ps.Runspace = rs; // 构建命令链:Write-Output Hello | Out-File -FilePath output.txt ps.AddCommand("Write-Output") .AddArgument("Hello") .AddCommand("Out-File") .AddParameter("FilePath", "output.txt"); ps.Invoke(); rs.Close();
内容的提问来源于stack exchange,提问作者Bob5421
相关产品推荐
相关产品推荐

