【问题标题】:C#.Net: Why is my Process.Start() hanging?C#.Net:为什么我的 Process.Start() 挂起?
【发布时间】:2008-08-29 08:36:36
【问题描述】:

我正在尝试以其他用户身份从我的网络应用程序运行批处理文件。由于某种原因,批处理文件挂起!我可以在任务管理器中看到“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);

如果您没有猜到,这个批处理文件会构建我的应用程序(与执行此命令的应用程序不同的应用程序)。

过程.开始(psi); line 应该立即返回,但批处理文件似乎挂起,没有执行。有什么想法吗?

编辑:有关批处理文件的内容,请参阅下面的答案。

  • 永远不会创建 output.txt。

我添加了这些行:

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

并在调试模式下逐步完成它们。代码挂在ReadLine() 上。我被难住了!

【问题讨论】:

  • 您能否发布您的批处理文件的代码,您是否尝试过从您的批处理文件中发出回显以便您可以看到它正在启动?

标签: c# .net


【解决方案1】:

我相信我已经找到了答案。微软似乎以其无限的智慧阻止了批处理文件在 Windows Server 2003 中由 IIS 执行。Brenden Tompkins 在这里有一个解决方法:

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

这对我不起作用,因为我的批处理文件使用 IF 和 GOTO,但它绝对适用于简单的批处理文件。

【讨论】:

    【解决方案2】:

    为什么不直接在 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);
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      没有看到 build.cmd 很难知道发生了什么,但是,您应该使用 Path.Combine(arg1, arg2); 构建路径这是构建路径的正确方法。

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

      我现在不记得了,但你不需要设置 UseShellExecute = true 吗?

      【讨论】:

        【解决方案4】:

        “调试”它的另一种可能性是使用标准输出,然后从中读取:

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

        【讨论】:

          【解决方案5】:

          为了“查看”正在发生的事情,我建议您将流程转换为更具交互性的内容(关闭 Echo)并放置一些“打印”以查看是否实际发生了任何事情。运行后 output.txt 文件中的内容是什么?

          bmail 真的执行了吗?

          在之后/之前打印一些照片,看看发生了什么。

          还要在参数中添加“@”,以防万一:

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

          它必须非常简单:)

          【讨论】:

            【解决方案6】:

            我的猜测是 build.cmd 正在等待某种用户交互/回复。如果您在最后使用“> logfile.txt”运算符记录命令的输出,它可能会帮助您找到问题。

            【讨论】:

              【解决方案7】:

              这是 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 提示特别有用。

              【讨论】:

                【解决方案8】:

                如果参数不正确,我认为 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 那么为什么不给出文件的完整路径呢?

                【讨论】:

                  【解决方案9】:

                  你们批次的结尾是什么?如果代码在 ReadLine 上挂起,那么问题可能是它无法读取批处理文件……

                  【讨论】:

                    猜你喜欢
                    • 2010-10-01
                    • 2015-07-09
                    • 1970-01-01
                    • 2015-07-28
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多