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;
}
これはローカルで実行されたプロセスの出力をキャプチャしますが、これはリモート プロセスでも機能しますか? (もう 1 つのあまり重要でない質問は、これがリモート プロセスでどのように機能するかということです。.Net Remoting は何らかの形で関与しており、Process のプロキシを取得していますか?)そうでない場合、それを行う方法は何ですか? プロセスが終了した後ではなく、生成中の出力が必要であることに注意してください。
これは、プロセスの終了をキャプチャしません。最初にプロセス ID をキャプチャしてから、別の実行空間から「Stop Process」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 には強く反対しています)。
更新:私がやったことは、リモートでスクリプトを実行するように指示されたpowershell.exeに(プロセスを開始するC#を介して-「powershell」+「-Command ...」を介して)呼び出すことでした(invoke-command)コンピューター。Powershell はデフォルトでリモート PC で生成された出力をキャプチャするため、この Process インスタンスを簡単に取得できました。キャンセルしたいときは、ローカルプロセスを強制終了しました。リモート コマンドのリターン コードは、よりトリッキーでした。コマンド、スクリプト、および C# スニペットをしばらく投稿します。