我正在尝试通过其 C# API 使用 PowerShell 来执行以下操作:
- 启动远程进程
- 终止他们
- 捕获远程进程的标准和错误输出(不是在进程终止之后,而是在生成该输出时)。
- 捕获远程进程的退出代码。
我正在使用以下 PowerShell 脚本启动远程进程:
$ps = new-object System.Diagnostics.Process
$ps
$ps.StartInfo.Filename = "c:\Echo.exe"
$ps.StartInfo.Arguments = ""
$ps.StartInfo.RedirectStandardOutput = $true
$ps.StartInfo.RedirectStandardError = $true
$ps.StartInfo.UseShellExecute = $false
$ps.start()
$ps.WaitForExit()
$ps.ExitCode
我的原型的 C# 部分如下所示:
// Note: in this example the process is started locally
using (Runspace runspace = RunspaceFactory.CreateRunspace(/*_remotePcConnectionInfo*/))
{
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
// Scripts.RunExecutable is that script above
pipeline.Commands.AddScript(Scripts.RunExecutable);
pipeline.InvokeAsync();
var process = (Process)pipeline.Output.Read().BaseObject;
bool started = (bool)pipeline.Output.Read().BaseObject;
// Not showing the dummy event handlers - they simply do a Console.WriteLine now.
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.BeginOutputReadLine();
// Not showing the dummy event handlers - they simply do a Console.WriteLine now.
process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
process.BeginErrorReadLine();
int processExitCode = (int) pipeline.Output.Read().BaseObject;
}
这确实捕获了本地运行的进程的输出,但这也适用于远程进程吗?(另一个不太重要的问题是:这如何适用于远程进程?.Net Remoting 是否以某种方式参与,我是否获得了 Process 的代理?)如果没有,有什么方法可以做到这一点?请注意,我需要输出,因为它正在生成,而不是在进程终止之后。
这不会捕获进程终止。我已经尝试通过先捕获进程 ID 然后从不同的运行空间运行“停止进程”PowerShell 脚本来进行终止。那失败了,因为“管道已经在运行”并且管道无法并行运行......然后我尝试从 C# 调用 process.Kill(),这适用于我的本地进程,但 SO 报告它不适用于远程进程...然后我尝试调整我的 PowerShell 脚本,使其包含一个全局变量和一个等待循环,但我从来没有弄清楚如何在管道启动后设置该变量。添加的循环如下所示:
while ($ps.HasExited -eq $false -and $global:cancelled -eq $false)
{
Start-Sleep -seconds 1
}
if ($global:cancelled -eq $true)
{
$ps.Kill()
}
所以,那也失败了。关于我的场景的流程终止有什么建议吗?
PowerShell 甚至适合这个吗?(我们强烈反对我们之前尝试使用的 openSSH,因为它存在分叉问题)。
更新:我最终做的是调用(通过 C# 启动进程——“powershell”+“-Command ...”)到 powershell.exe,它被告知在远程执行脚本(调用命令)电脑。Powershell 默认捕获远程 PC 上产生的输出,因此我可以轻松获取 Process 实例的这个。当我想取消时,我杀死了本地进程。远程命令的返回码比较棘手。稍后我将发布命令、脚本和 C#-snippet。