我正在尝试从我的网络应用中以另一个用户身份运行批处理文件。出于某种原因,批处理文件挂起!我可以看到“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(psi);行应该立即返回,但批处理文件似乎挂起,没有执行。有什么想法吗?
编辑:请参阅下面的答案,了解批处理文件的内容。
我添加了这些内容:
psi.RedirectStandardOutput = true;
Process p = Process.Start(psi);
String outp = p.StandardOutput.ReadLine();
并在调试模式下逐步完成它们。代码挂在ReadLine()
上。我很难过!
答案 0 :(得分:5)
我相信我找到了答案。似乎微软以他们无限的智慧阻止了批处理文件被Windows Server 2003中的IIS执行.Brenden Tompkins在这里有一个解决方法:
http://codebetter.com/blogs/brendan.tompkins/archive/2004/05/13/13484.aspx
这对我不起作用,因为我的批处理文件使用IF和GOTO,但它肯定适用于简单的批处理文件。
答案 1 :(得分: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 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 :(得分:2)
如果没有看到build.cmd,很难说出发生了什么,但是,你应该使用Path.Combine(arg1,arg2)构建路径;这是构建路径的正确方法。
Path.Combine( Environment.SystemDirectory, "cmd.exe" );
我现在不记得了,但你不必设置UseShellExecute = true吗?
答案 3 :(得分:1)
“调试”它的另一种可能性是使用standardoutput然后从中读取:
psi.RedirectStandardOutput = True;
Process proc = Process.Start(psi);
String whatever = proc.StandardOutput.ReadLine();
答案 4 :(得分:1)
为了“看到”正在发生的事情,我建议你将这个过程转换成更具互动性的东西(关掉Echo off)并放一些“打印”以查看是否真的发生了什么。运行此命令后,output.txt文件中的内容是什么?
bmail是否实际执行?
在之前/之前放一些印刷品以查看发生了什么。
同样在参数中添加“@”,以防万一:
psi.Arguments = @"/q /c build.cmd";
必须非常简单:)
答案 5 :(得分:0)
我的猜测是build.cmd正在等待某种用户交互/回复。如果您在结尾处使用“> logfile.txt ”运算符记录命令的输出,则可能会帮助您找到问题。
答案 6 :(得分: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 build@example.com -t josh@example.com -a "Build failed." -m output.txt -h
:end
del output.txt
如你所见,我小心不输出任何东西。这一切都发送到一个文件,如果构建失败,它会通过电子邮件发送给我。我实际上已经将这个文件作为计划任务运行了一段时间。我正在尝试构建一个允许我按需运行它的Web应用程序。
感谢大家的帮助! Path.Combine提示特别有用。
答案 7 :(得分:0)
我认为如果参数不正确,cmd.exe会挂起。
如果批处理正确执行,那么我就会像这样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();
也可能是cmd.exe找不到build.cmd所以为什么不给出文件的完整路径呢?
答案 8 :(得分:0)
批量的最终要点是什么?如果代码在ReadLine上挂起,则问题可能是它无法读取批处理文件......