C # .Net: Почему мой Process.Start () зависает? - PullRequest
13 голосов
/ 29 августа 2008

Я пытаюсь запустить командный файл, как другой пользователь, из моего веб-приложения. По какой-то причине командный файл зависает! Я вижу «cmd.exe», запущенный в диспетчере задач, но он просто сидит навсегда, его невозможно убить, а пакетный файл не запущен. Вот мой код:

SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
    password.AppendChar(c);

ProcessStartInfo psi = new ProcessStartInfo();
psi.WorkingDirectory = @"c:\build";
psi.FileName = Environment.SystemDirectory + @"\cmd.exe";
psi.Arguments = "/q /c build.cmd";
psi.UseShellExecute = false;
psi.UserName = "builder";
psi.Password = password;
Process.Start(psi);

Если вы не догадались, этот пакетный файл создает мое приложение (иное, чем приложение, выполняющее эту команду).

Process.Start (фунтов на квадратный дюйм); строка возвращается немедленно, как и должно быть, но командный файл, кажется, просто зависает без выполнения. Есть идеи?

РЕДАКТИРОВАТЬ: См. Мой ответ ниже для содержимого командного файла.

  • Файл output.txt никогда не создается.

Я добавил эти строки:

psi.RedirectStandardOutput = true;
Process p = Process.Start(psi);
String outp = p.StandardOutput.ReadLine();

и пошагово прошел их в режиме отладки. Код висит на ReadLine(). Я в тупике!

Ответы [ 9 ]

5 голосов
/ 01 сентября 2008

Мне кажется, я нашел ответ. Похоже, что Microsoft, несмотря на всю свою бесконечную мудрость, заблокировала выполнение командных файлов IIS в Windows Server 2003. У Брендена Томпкинса есть обходной путь:

http://codebetter.com/blogs/brendan.tompkins/archive/2004/05/13/13484.aspx

Это не будет работать для меня, потому что мой пакетный файл использует IF и GOTO, но он определенно будет работать для простых пакетных файлов.

3 голосов
/ 01 сентября 2008

Почему бы просто не выполнять всю работу в C # вместо использования пакетных файлов?

Мне было скучно, поэтому я написал это очень быстро, это просто набросок того, как я это сделаю, так как я не знаю, что делают переключатели командной строки или пути к файлам.

using System;
using System.IO;
using System.Text;
using System.Security;
using System.Diagnostics;

namespace asdf
{
    class StackoverflowQuestion
    {
        private const string MSBUILD = @"path\to\msbuild.exe";
        private const string BMAIL = @"path\to\bmail.exe";
        private const string WORKING_DIR = @"path\to\working_directory";

        private string stdout;
        private Process p;

        public void DoWork()
        {
            // build project
            StartProcess(MSBUILD, "myproject.csproj /t:Build", true);
        }

        public void StartProcess(string file, string args, bool redirectStdout)
        {
            SecureString password = new SecureString();
            foreach (char c in "mypassword".ToCharArray())
                password.AppendChar(c);

            ProcessStartInfo psi = new ProcessStartInfo();
            p = new Process();
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.WorkingDirectory = WORKING_DIR;
            psi.FileName = file;
            psi.UseShellExecute = false;
            psi.RedirectStandardOutput = redirectStdout;
            psi.UserName = "builder";
            psi.Password = password;
            p.StartInfo = psi;
            p.EnableRaisingEvents = true;
            p.Exited += new EventHandler(p_Exited);
            p.Start();

            if (redirectStdout)
            {
                stdout = p.StandardOutput.ReadToEnd();
            }
        }

        void p_Exited(object sender, EventArgs e)
        {
            if (p.ExitCode != 0)
            {
                // failed
                StringBuilder args = new StringBuilder();
                args.Append("-s k2smtpout.secureserver.net ");
                args.Append("-f build@example.com ");
                args.Append("-t josh@example.com ");
                args.Append("-a \"Build failed.\" ");
                args.AppendFormat("-m {0} -h", stdout);

                // send email
                StartProcess(BMAIL, args.ToString(), false);
            }
        }
    }
}
2 голосов
/ 29 августа 2008

Не видя build.cmd, трудно сказать, что происходит, однако вы должны построить путь с помощью Path.Combine (arg1, arg2); Это правильный способ построить путь.

Path.Combine( Environment.SystemDirectory, "cmd.exe" );

Я не помню сейчас, но вам не нужно устанавливать UseShellExecute = true?

1 голос
/ 29 августа 2008

Чтобы «увидеть», что происходит, я бы посоветовал вам превратить процесс в нечто более интерактивное (отключить «Эхо») и нанести несколько «отпечатков», чтобы увидеть, происходит ли что-нибудь на самом деле. Что находится в файле output.txt после запуска?

bmail действительно выполняется?

Положите несколько отпечатков после / до, чтобы увидеть, что происходит.

Также добавьте «@» к аргументам, на всякий случай:

psi.Arguments = @"/q /c build.cmd";

Это должно быть что-то очень простое:)

1 голос
/ 29 августа 2008

Еще одна возможность «отладки» - использовать стандартный вывод и затем прочитать из него:

psi.RedirectStandardOutput = True;
Process proc = Process.Start(psi);
String whatever = proc.StandardOutput.ReadLine();
0 голосов
/ 01 сентября 2008

Каковы конечные показатели вашей партии? Если код зависает на ReadLine, проблема может заключаться в том, что он не может прочитать командный файл ...

0 голосов
/ 29 августа 2008

Я думаю, что cmd.exe зависает, если параметры неверны.

Если пакет выполняется правильно, я бы просто вместо этого выполнил его.

ProcessStartInfo psi = new ProcessStartInfo();
Process p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = @"c:\build";
psi.FileName = @"C:\build\build.cmd";
psi.UseShellExecute = true;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.Start();

Также возможно, что cmd.exe просто не может найти build.cmd, так почему бы не указать полный путь к файлу?

0 голосов
/ 29 августа 2008

Вот содержимое build.cmd:

@echo off
set path=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;%path%

msbuild myproject.csproj /t:Build > output.txt
IF NOT ERRORLEVEL 1 goto :end

:error
bmail -s k2smtpout.secureserver.net -f build@example.com -t josh@example.com -a "Build failed." -m output.txt -h

:end
del output.txt

Как видите, я осторожен, чтобы ничего не выводить. Все это относится к файлу, который отправляется мне по электронной почте в случае сбоя сборки. На самом деле, я довольно долго запускал этот файл как запланированное задание по ночам. Я пытаюсь создать веб-приложение, которое позволяет запускать его по требованию.

Спасибо всем за помощь! Совет Path.Combine был особенно полезен.

0 голосов
/ 29 августа 2008

Я думаю, что build.cmd ожидает какого-то взаимодействия с пользователем / ответа. Если вы зарегистрируете вывод команды с оператором «> logfile.txt » в конце, это может помочь вам найти проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...