Я пытаюсь использовать PowerShell через API С#, чтобы сделать следующее:
- запускать удаленные процессы
- прекратить их
- захватывать стандартный вывод и вывод об ошибках удаленных процессов (не после завершения процесса, а по мере создания этого вывода).
- захватить код выхода удаленных процессов.
Я запускаю удаленные процессы со следующим скриптом 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 в некоторых процессах? способ, и получу ли я прокси для процесса?) Если нет, то как это сделать? Имейте в виду, что мне нужен вывод по мере его создания, а не после завершения процесса.
Это не фиксирует завершение процесса. Я попытался выполнить завершение, сначала захватив идентификатор процесса, а затем запустив сценарий PowerShell «Остановить процесс» из другого пространства выполнения. Это не удалось, потому что «конвейер уже запущен», а конвейеры не могут работать параллельно... Затем я попытался вызвать process.Kill() из C#, это сработало для моего локального процесса, но 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 по умолчанию фиксирует выходные данные, созданные на удаленном ПК, поэтому я мог легко получить это из экземпляра процесса. Когда я хотел отменить, я убил локальный процесс. Код возврата удаленной команды был сложнее. Через некоторое время я опубликую команду, скрипт и C#-фрагмент.