2008-08-29 1 views
12

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

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 (psi); строка возвращает сразу, как и должно быть, но командный файл просто висит, не выполняя. Есть идеи?

EDIT: См. Мой ответ ниже для содержимого командного файла.

  • Не удалось создать output.txt.

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

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

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

+0

Можете ли вы опубликовать код для своего командного файла и попробовали испускать эхо из своего командного файла, чтобы вы могли видеть, что он запускается? – 2008-08-29 08:40:03

ответ

5

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

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

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

0

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

2

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

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

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

1

Другая возможность «отладки» это использовать standardoutput, а затем читать из него:

psi.RedirectStandardOutput = True; 
Process proc = Process.Start(psi); 
String whatever = proc.StandardOutput.ReadLine(); 
0

Вот содержимое 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 [email protected] -t [email protected] -a "Build failed." -m output.txt -h 

:end 
del output.txt 

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

Спасибо за помощь всем до сих пор! Кончик Path.Combine был особенно полезен.

1

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

Выполняется ли bmail?

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

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

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

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

0

Я думаю, что 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

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

3

Почему бы просто не выполнять всю работу на 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 [email protected] "); 
       args.Append("-t [email protected] "); 
       args.Append("-a \"Build failed.\" "); 
       args.AppendFormat("-m {0} -h", stdout); 

       // send email 
       StartProcess(BMAIL, args.ToString(), false); 
      } 
     } 
    } 
} 
Смежные вопросы