Подтвердить что ты не робот

Служба зависает в 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(). Мне нужно убить командный файл из процесса, чтобы продолжить. (Я уверен, что файл существует, поскольку я вижу его в списке процессов.)

Как я могу исправить эту зависание?

Обновление # 1:

Код Kevin позволяет мне получать выходные данные. Один из моих пакетных файлов все еще висит.

"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 на Пользователь, и я установил пароль администратора и пароль, но ничего.

4b9b3361

Ответ 1

Вот что я использую для выполнения пакетных файлов:

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();

Я не знаю, будет ли это делать трюк для вас, но у меня нет проблемы с этим висит.

Ответ 2

с использованием System;   используя System.Collections.Generic;   используя System.Linq;   используя System.Text;   использование System.Diagnostics;   пространство имен VG   {       класс VGe       {           [STAThread]           static void Main (string [] args)           {               Process proc = null;               пытаться               {
                  string targetDir = string.Format(@ "D:\adapters\setup" );//это где mybatch.bat лежит                   proc = new Process();                   proc.StartInfo.WorkingDirectory = targetDir;                   proc.StartInfo.FileName = "mybatch.bat";                   proc.StartInfo.Arguments = string.Format( "10" );//это аргумент                   proc.StartInfo.CreateNoWindow = false;                   proc.Start();                   proc.WaitForExit();               }               catch (Exception ex)               {                   Console.WriteLine( "Исключено: {0}, {1}", ex.Message, ex.StackTrace.ToString());               }           }       }   }

Ответ 3

            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();

Протестировано, работает ясно.

Ответ 4

Что делает пакетный файл? Вы уверены, что процесс запускается с достаточным количеством привилегий для выполнения командного файла? Услуги могут быть ограничены в том, что им разрешено делать.

Также убедитесь, что вы делаете что-то вроде команды usin для перезаписи файла, который вы делаете примерно так:

echo Y | copy foo.log c:\backup\

Кроме того, убедитесь, что вы используете полные пути для командных команд и т.д. Если командный файл запускает графическое приложение в каком-то режиме "Консоль", это может быть проблемой. Помните, что у служб нет "рабочего стола" (если только вы не разрешаете "взаимодействовать с рабочим столом" ), чтобы рисовать любые окна или окна сообщений. В вашей программе вы можете открыть каналы stdout и stderr и прочитать их во время выполнения, если вы получаете сообщения об ошибках или что-то еще.

WebServices, вероятно, выполняется как учетная запись IUSR или анонимная учетная запись, которая когда-либо была, что может быть проблемой для вас. Если он работает, когда вы запускаете его в консоли, это только первый шаг.:)

Я не помню, если System.Diagnostics. доступны только в отладке или нет. Наверное, нет, но некоторые из них могут быть. Я должен проверить это на ya.

Надеюсь, это даст вам некоторые идеи.

Larry

Ответ 5

pg_dump.exe, вероятно, запрашивает ввод пользователя. Требует ли эта база данных аутентификация? Вы полагаетесь на любые переменные ОКРУЖАЮЩЕЙ СРЕДЫ, которые не будут присутствовать в сервисе? Я не знаю pg_dump, но каковы другие возможные причины запроса на ввод?

Ответ 6

Следующий шаг, который я хотел бы предпринять, - это запустить отладчик и посмотреть, сможете ли вы узнать, что ожидает программа. Если вы отлаживаетесь при отладке в сборке, вы можете получить ИДЕИ того, что происходит с помощью таких инструментов, как ProcExp, FileMon и т.д.

Являюсь сервисом Windows SERVICE, а не веб-сервисом, имеет немалую разницу. В любом случае, вы пробовали мое предложение установить "Разрешить службу взаимодействовать с рабочим столом"?

Если вы в отчаянии, попробуйте запустить cmd.exe вместо вашего пакетного файла. Затем, используя параметры cmd.exe cmd, вы можете запустить ИТ-пакет командного файла. Это, вероятно, даст вам окно подсказки cmd для просмотра фактического вывода, если вы включите взаимодействие с рабочим столом.

Для получения полной справки о cmd.exe просто введите cmd/? в любой командной строке.

Larry

Ответ 7

Вот решение. Решение непонятно, потому что я изменил так много времени на код и теперь он работает!

Я попытался использовать учетную запись пользователя, и это не то, что сработало. Используйте 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();

Спасибо всем, я буду голосовать, и принимать Кевина, так как он помогает мне с самого начала. Очень странно, потому что сейчас это работает...

Ответ 8

Даок, похоже, единственное, что вы изменили, это период ожидания на начальном WaitForExit(). Вы должны быть ОЧЕНЬ осторожны. Если что-то ДЕЛАЕТ повесить ваш сервис, он НИКОГДА не вернется (и, ну, в значительной степени работа такая, как это было для вас до сих пор.. хех), но это не будет хорошо для конечных пользователей...

Теперь, возможно, вы знаете, что заставляет это зависать, вы можете отладить его дальше и найти полное решение...

Это, или открутить это в каком-то потоке, который вы можете контролировать, и убить, если он слишком долго висит.

Только мои 2 цента стоит, что обычно не много.;)