C#.Net:为什么我的 Process.Start() 挂了?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34183/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#.Net: Why is my Process.Start() hanging?
提问by Josh Hinman
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:
我正在尝试以另一个用户的身份从我的 Web 应用程序运行批处理文件。由于某种原因,批处理文件挂起!我可以在任务管理器中看到“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);
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?
Process.Start(psi); 行立即返回,因为它应该,但批处理文件似乎挂起,没有执行。有任何想法吗?
EDIT:See my answer below for the contents of the batch file.
编辑:有关批处理文件的内容,请参阅下面的答案。
- The output.txt never gets created.
- output.txt 永远不会被创建。
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!
并在调试模式下逐步完成它们。代码挂在ReadLine()
. 我难住了!
采纳答案by Josh Hinman
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:
我相信我已经找到了答案。似乎微软以其无限的智慧阻止了 IIS 在 Windows Server 2003 中执行批处理文件。 Brenden Tompkins 有一个解决方法:
http://codebetter.com/blogs/brendan.tompkins/archive/2004/05/13/13484.aspx
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.
这对我不起作用,因为我的批处理文件使用 IF 和 GOTO,但它肯定适用于简单的批处理文件。
回答by Espo
My guess would be that the build.cmd is waiting for some sort of user-interaction/reply. If you log the output of the command with the "> logfile.txt" operator at the end, it might help you find the problem.
我的猜测是 build.cmd 正在等待某种用户交互/回复。如果您在末尾使用“ > logfile.txt” 操作符记录命令的输出,它可能会帮助您找到问题。
回答by Martin Marconcini
Without seeing the build.cmd it's hard to tell what is going on, however, you should build the path using Path.Combine(arg1, arg2); It's the correct way to build a path.
没有看到 build.cmd 很难知道发生了什么,但是,您应该使用 Path.Combine(arg1, arg2); 构建路径。这是构建路径的正确方法。
Path.Combine( Environment.SystemDirectory, "cmd.exe" );
I don't remember now but don't you have to set UseShellExecute = true ?
我现在不记得了,但您不必设置 UseShellExecute = true 吗?
回答by Biri
Another possibility to "debug" it is to use standardoutput and then read from it:
“调试”它的另一种可能性是使用标准输出,然后从中读取:
psi.RedirectStandardOutput = True;
Process proc = Process.Start(psi);
String whatever = proc.StandardOutput.ReadLine();
回答by Josh Hinman
Here's the contents of build.cmd:
这是 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
As you can see, I'm careful not to output anything. It all goes to a file that gets emailed to me if the build happens to fail. I've actually been running this file as a scheduled task nightly for quite a while now. I'm trying to build a web app that allows me to run it on demand.
正如你所看到的,我很小心不输出任何东西。如果构建碰巧失败,这一切都将转到一个文件,该文件会通过电子邮件发送给我。实际上,我已经将这个文件作为每晚的计划任务运行了很长一段时间。我正在尝试构建一个允许我按需运行它的网络应用程序。
Thanks for everyone's help so far! The Path.Combine tip was particularly useful.
到目前为止,感谢大家的帮助!Path.Combine 提示特别有用。
回答by Martin Marconcini
In order to "see" what's going on, I'd suggest you transform the process into something more interactive (turn off Echo off) and put some "prints" to see if anything is actually happening. What is in the output.txt file after you run this?
为了“查看”正在发生的事情,我建议您将过程转换为更具交互性的内容(关闭 Echo)并进行一些“打印”以查看是否确实发生了任何事情。运行后 output.txt 文件中有什么?
Does the bmail actually executes?
bmail 真的执行了吗?
Put some prints after/before to see what's going on.
在之后/之前打印一些照片,看看发生了什么。
Also add "@" to the arguments, just in case:
还要在参数中添加“@”,以防万一:
psi.Arguments = @"/q /c build.cmd";
It has to be something very simple :)
它必须非常简单:)
回答by sieben
I think cmd.exe hangs if the parameters are incorrect.
如果参数不正确,我认为 cmd.exe 会挂起。
If the batch executes correctly then I would just shell execute it like this instead.
如果批处理正确执行,那么我只会像这样 shell 执行它。
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();
Also it could be that cmd.exe just can't find build.cmd so why not give the full path to the file?
也可能是 cmd.exe 找不到 build.cmd 那么为什么不提供文件的完整路径呢?
回答by Martin Marconcini
What are the endlines of you batch? If the code hangs on ReadLine, then the problem might be that it's unable to read the batch file…
你们批次的终点是什么?如果代码挂在 ReadLine 上,那么问题可能是它无法读取批处理文件......
回答by sieben
Why not just do all the work in C# instead of using batch files?
为什么不在 C# 中完成所有工作而不是使用批处理文件?
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);
}
}
}
}