Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#.Net: Why is my Process.Start() hanging?

Tags:

c#

.net

I'm trying to run a batch file, as another user, from my web app. For some reason, the batch file hangs! I can see "cmd.exe" running in the task manager, but it just sits there forever, unable to be killed, and the batch file is not running. Here's my code:

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

If you didn't guess, this batch file builds my application (a different application than the one that is executing this command).

The Process.Start(psi); line returns immediately, as it should, but the batch file just seems to hang, without executing. Any ideas?

EDIT: See my answer below for the contents of the batch file.

  • The output.txt never gets created.

I added these lines:

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

and stepped through them in debug mode. The code hangs on the ReadLine(). I'm stumped!

like image 598
Josh Hinman Avatar asked Aug 29 '08 08:08

Josh Hinman


2 Answers

I believe I've found the answer. It seems that Microsoft, in all their infinite wisdom, has blocked batch files from being executed by IIS in Windows Server 2003. Brenden Tompkins has a work-around here:

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

That won't work for me, because my batch file uses IF and GOTO, but it would definitely work for simple batch files.

like image 177
Josh Hinman Avatar answered Sep 18 '22 09:09

Josh Hinman


Why not just do all the work in C# instead of using batch files?

I was bored so i wrote this real quick, it's just an outline of how I would do it since I don't know what the command line switches do or the file paths.

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);
            }
        }
    }
}
like image 37
sieben Avatar answered Sep 18 '22 09:09

sieben