Служба зависает в WaitForExit после вызова командного файла
У меня есть служба, которая иногда вызывает пакетный файл. Пакетный файл занимает 5-10 секунд для выполнения:
System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process proc.StartInfo.FileName = fileName; proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; proc.StartInfo.CreateNoWindow = true; proc.Start(); proc.WaitForExit();
Файл существует, и код работает, когда я запускаю один и тот же код в консоли. Однако, когда он запускается внутри службы, он зависает в WaitForExit()
. Мне нужно убить командный файл из процесса, чтобы продолжить. (Я уверен, что файл существует, поскольку я вижу его в списке процессов.)
Как я могу исправить это зависание?
- Как отправить местоположение устройства на сервер при необходимости
- Слушатель Android Location в службе не работает, пока я не активирую WiFi / мобильную сеть
- Как автоматически перезапустить службу, даже если пользователь закроет ее?
- Как включить функцию AutoStart для моего приложения в приложении безопасности Xiaomi Security App программно в android
- Как SID отличается от имени службы в Oracle tnsnames.ora
Обновление # 1:
Код Кевина позволяет мне получить выход. Один из моих пакетных файлов все еще висит.
“C: \ EnterpriseDB \ Postgres \ 8.3 \ bin \ pg_dump.exe” -i -h localhost -p 5432 -U postgres -F p -a -D -v -f “c: \ backupcasecocher \ backupdateevent2008.sql” -t “\” public \ “. \” dateevent \ “” “DbTest”
Другой командный файл:
“C: \ EnterpriseDB \ Postgres \ 8.3 \ bin \ vacuumdb.exe” -U postgres -d DbTest
Я проверил путь, и путь postgresql
в порядке. Каталог вывода существует и по-прежнему работает вне службы. Есть идеи?
Обновление № 2:
Вместо пути командного файла я написал «C: \ EnterpriseDB \ Postgres \ 8.3 \ bin \ pg_dump.exe» для proc.StartInfo.FileName
и добавил все параметры в proc.StartInfo.Arguments
. Результаты не изменяются, но я вижу pg_dump.exe
в окне процесса. Опять же это происходит только внутри службы.
Обновление № 3:
Я запустил службу с пользователем в группе администратора, но безрезультатно. Я восстановил значение null
для имени пользователя и пароля службы
Обновление № 4:
Я создал простую службу для записи трассировки в журнале событий и выполнения пакетного файла, содержащего в нем «dir». Теперь он будет зависать в proc.Start();
– Я попытался изменить учетную запись из LocalSystem на пользователя, и я установил пароль администратора и пароль, но ничего.
- Должен ли ServiceStack быть служебным слоем в приложении MVC или должен ли он вызвать сервисный уровень?
- Получение контекста приложения
- Ошибка ссылки на службу: не удалось сгенерировать код для ссылки на службу
- Что такое нелексические времена жизни?
- Использование Alarmmanager для запуска службы в определенное время
- Использование Process.Start () для запуска процесса как другого пользователя из службы Windows
- Запрашивать пароль перед удалением приложения
- Приложение Spring Boot как услуга
Вот что я использую для выполнения пакетных файлов:
proc.StartInfo.FileName = target; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.UseShellExecute = false; proc.Start(); proc.WaitForExit ( (timeout <= 0) ? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND * NO_SECONDS_IN_A_MINUTE ); errorMessage = proc.StandardError.ReadToEnd(); proc.WaitForExit(); outputMessage = proc.StandardOutput.ReadToEnd(); proc.WaitForExit();
Я не знаю, поможет ли вам этот трюк, но у меня нет проблемы с этим.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace VG { class VGe { [STAThread] static void Main(string[] args) { Process proc = null; try { string targetDir = string.Format(@"D:\adapters\setup");//this is where mybatch.bat lies proc = new Process(); proc.StartInfo.WorkingDirectory = targetDir; proc.StartInfo.FileName = "mybatch.bat"; proc.StartInfo.Arguments = string.Format("10");//this is argument proc.StartInfo.CreateNoWindow = false; proc.Start(); proc.WaitForExit(); } catch (Exception ex) { Console.WriteLine("Exception Occurred :{0},{1}", ex.Message,ex.StackTrace.ToString()); } } } }
string targetDir = string.Format(@"D:\");//PATH proc = new Process(); proc.StartInfo.WorkingDirectory = targetDir; proc.StartInfo.FileName = "GetFiles.bat"; proc.StartInfo.Arguments = string.Format("10");//argument proc.StartInfo.CreateNoWindow = false; proc.Start(); proc.WaitForExit();
Протестировано, работает понятно.
Что делает пакетный файл? Вы уверены, что процесс запускается с достаточным количеством привилегий для выполнения командного файла? Услуги могут быть ограничены тем, что им разрешено делать.
Также убедитесь, что вы делаете что-то вроде команды usin для перезаписи файла, который вы делаете примерно так:
echo Y | copy foo.log c:\backup\
Кроме того, убедитесь, что вы используете полные пути для командных команд и т. Д. Если командный файл запускает графическое приложение в каком-то режиме «Консоль», это тоже может быть проблемой. Помните, что у служб нет «рабочего стола» (если только вы не разрешаете «взаимодействовать с рабочим столом»), чтобы рисовать любые windows или windows сообщений. В вашей программе вы можете открыть каналы stdout и stderr и прочитать их во время выполнения, если вы получаете сообщения об ошибках или что-то еще.
WebServices, вероятно, выполняется как учетная запись IUSR или анонимная учетная запись, которая когда-либо была так, что может быть проблемой для вас. Если он работает, когда вы запускаете его в консоли, это только первый шаг. 🙂
Я не помню, если System.Diagnostics. доступны только в отладке или нет. Наверное, нет, но некоторые из них могут быть. Я должен проверить это для тебя.
Надеюсь, это даст вам некоторые идеи.
Larry
Вероятно, pg_dump.exe вызывает запрос пользователя. Требует ли эта firebase database аутентификация? Вы полагаетесь на любые переменные ОКРУЖАЮЩЕЙ СРЕДЫ, которые не будут присутствовать в сервисе? Я не знаю pg_dump, но каковы другие возможные причины, по которым он будет запрашивать ввод?
Следующий шаг, который я хотел бы предпринять, – это запустить отладчик и посмотреть, можете ли вы сказать, что ожидает программа. Если вы отлаживаетесь при отладке в сборке, вы можете получить ИДЕИ того, что происходит с помощью таких инструментов, как ProcExp, FileMon и т. Д.
Быть оконной службой, а не веб-службой, имеет довольно большое значение. В любом случае, вы попробовали мое предложение установить «Разрешить службу взаимодействовать с рабочим столом»?
Если вы в отчаянии, вы можете попробовать запустить cmd.exe вместо вашего пакетного файла. Затем, используя параметры cmd.exe, вы можете запустить пакетный файл. Это, вероятно, даст вам окно подсказки cmd для просмотра фактического вывода, если вы включите взаимодействие с рабочим столом.
Для полной помощи на cmd.exe просто введите cmd /? в любой командной строке.
Larry
Вот решение. Решение непонятно, потому что я изменил так много времени на код, и теперь он работает!
Я попытался использовать учетную запись пользователя, и это не то, что сработало. Используйте LocalSystem. Вот код, который выполняется, в основном то, что дал мне Кевин.
System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = fileName; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.UseShellExecute = false; proc.Start(); proc.WaitForExit(); output1 = proc.StandardError.ReadToEnd(); proc.WaitForExit(); output2 = proc.StandardOutput.ReadToEnd(); proc.WaitForExit();
Благодарю всех вас, я буду голосовать за всех и принимать Кевина, так как он помогает мне с самого начала. Очень странно, потому что сейчас это работает …
Даок, похоже, единственное, что вы изменили, это период ожидания на начальном WaitForExit (). Вы должны быть ОЧЕНЬ осторожны. Если что-то ДЕЛАЕТ повесить ваш сервис, он НИКОГДА не вернется (и хорошо, в значительной степени работа, как это было для вас до сих пор .. хех), но это не будет хорошо для конечных пользователей …
Теперь, возможно, вы знаете, что заставляет это висеть, вы можете отладить его дальше и найти полное решение …
Это, или открутить это в каком-то streamе, который вы можете контролировать, и убить, если он слишком долго висит.
Только мои 2 цента стоит, что обычно не много. 😉