У меня есть пакетный файл, выполняющий повторяющуюся работу, который выполняется из приложения C # (менеджера заданий) как процесс, и его необходимо остановить «мягким» способом (не Process.Kill()
, а скорее чтение вводамежду рабочими итерациями).
Я выбрал перенаправление stdin скрипта и отправку строки "stop", когда пришло время.В пакете я должен прочитать команду «стоп» (или даже любой ввод, просто получить строку) и выйти.Однако это легче сказать, чем сделать.
Следующая команда получает любые входные данные и выходит:
set /p x=&exit
Но, будучи однопоточным, пакет не может выполнять итерации во время ожиданиядля ввода.Итак, я вижу 2 способа справиться с этим:
1.Многопоточность
Я не нашел никакого способа сделать это в пакетном режиме, кроме команды start
.Я попробовал это:
start set /p x=&exit
Но, похоже, он создает новый процесс , поэтому мой ввод не достигает его, и даже если я нашел способ перенаправить его туда, вызываявыход в него не помог бы мне никоим образом, так как это не процесс моей партии.Вот полный пример скрипта:
@echo off
start set /p x=&exit
:work
ping 127.0.0.1
goto :work
2.Тайм-аут при чтении ввода
Здесь есть команда choice
, как показано здесь .Но тайм-аут не работает, когда пакет выполняется из C # - команда продолжает ожидать ввода, хотя тайм-аут и значение по умолчанию определены.Вот полный пример сценария:
@echo off
:work
ping 127.0.0.1
choice /T 5 /C sc /D c
set _e=%ERRORLEVEL%
if %_e%==1 echo Stopped
if %_e%==2 echo Continue&goto :work
"s" из "stop" достаточно для успешной остановки сценария, но происходит только 1 итерация - команда выбора просто ожидает ввода.Вот код C #, порождающий процесс, довольно стандартный:
Process script = new Process();
script.StartInfo = new ProcessStartInfo("batfile.bat");
script.StartInfo.UseShellExecute = false;
script.StartInfo.WorkingDirectory = Environment.GetEnvironmentVariable("ROOT");
script.StartInfo.RedirectStandardInput = true;
script.StartInfo.RedirectStandardOutput = true;
script.StartInfo.RedirectStandardError = true;
script.OutputDataReceived += new DataReceivedEventHandler(HandleStdout);
script.ErrorDataReceived += new DataReceivedEventHandler(HandleStderr);
script.Start();
Я подозреваю, что он как-то связан с перенаправлениями: stdout висит на строке [S, C]? , потому что естьпосле него нет новой строки.Но мне нужны эти перенаправления ...
Конечно, есть 3-й вариант , который отправляет ввод "continue" или пустую строку каждую секунду или около того, поэтому скрипт просто должен выглядетьдля "стопа", но, на мой взгляд, это немного уродливо, поэтому я стараюсь избежать этого любой ценой, особенно если я использую вариант 1 или 2 или получу лучшее предложение.