【发布时间】:2015-04-19 21:15:20
【问题描述】:
我整个上午都在寻找和试验这个,我被难住了。我有一个在 IIS 中运行并调用以下 c# 函数的 aspx 页面。我试图让它运行一个 cmd 文件并从 cmd 文件返回输出。我在下面的代码中试验了五个不同的选项:
protected String RunMyCmdFileAndGetResponse() {
Process proc = new Process ();
proc.StartInfo.FileName = @"c:\Windows\System32\cmd.exe";
// proc.StartInfo.Arguments = @"/c echo hello"; <== 1
// proc.StartInfo.Arguments = @"/c c:\mypath\myfile_badname.cmd"; <== 2
// proc.StartInfo.Arguments = @"/c type c:\mypath\myfile.cmd"; <== 3
proc.StartInfo.Arguments = @"/c c:\mypath\myfile.cmd"; // <== 4
// proc.StartInfo.Arguments = @"/c call c:\mypath\myfile.cmd"; <== 5
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
string response = proc.StandardOutput.ReadToEnd();
response += proc.StandardError.ReadToEnd();
proc.WaitForExit();
return response;
}
Cmd 文件 c:\mypath\myfile.cmd 内容为:
@echo test line 1 > c:\mypath\myfilelog.txt
@echo test line 2
此 cmd 文件在手动运行时按预期工作,生成 myfilelog.txt 并返回测试行 2。使用 c# 代码执行时:
- 选项 1 有效 - 按预期返回“hello”响应。
- 选项 2 按预期失败,表明 myfile_badname.cmd 未被识别为有效命令
- 选项 3 按预期工作 - 它返回 myfile.cmd 的内容作为响应 - 这确认我能够找到并读取文件。
- 选项 4 不起作用 - 尽我所能,它应该。它不挂机,而且根本不返回任何响应,也不执行 cmd 文件(没有产生 myfilelog.txt)。
- 选项 5 - 结果与选项 4 相同。
注意 - 我也尝试修改 myfile.cmd 以删除第 1 行(创建日志文件)并且只保留第 2 行来回显响应。以防万一创建日志文件是权限问题。结果一样。
任何帮助将不胜感激!
已更新以添加解决方案:
@MaxOvrdrv 的回答让我有了不同的想法。在使用 UseShellExecute = false 的 IIS 上下文中运行 Process.Start 时确实似乎存在某种限制 - 如果主要参数是可执行文件(cmd 文件、脚本文件等),它将不会运行它。我尝试将 SomeExample.cmd 传递给 cmd.exe,并将 SomeExample.js 传递给 cscript.exe。
但是...我能够用一定程度的间接来欺骗它,这样可执行文件名不再是第一个参数,而且它工作得很好。
运行 cmd 文件:
string theResponse = RunMyCmdAndGetResponse(@"c:\somepath\mycmd.cmd");
protected String RunMyCmdAndGetResponse(string cmdPath) {
Process proc = new Process ();
proc.StartInfo.FileName = @"c:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = "/c cmd /c " + cmdPath;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
string response = proc.StandardOutput.ReadToEnd();
response += proc.StandardError.ReadToEnd();
return response;
}
运行脚本文件:
string theResponse = RunMyScriptAndGetResponse(@"c:\somepath\myscript.js");
protected String RunMyScriptAndGetResponse(string scriptPath) {
Process proc = new Process ();
proc.StartInfo.FileName = @"c:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = "/c cscript //nologo " + scriptPath;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
string response = proc.StandardOutput.ReadToEnd();
response += proc.StandardError.ReadToEnd();
return response;
}
【问题讨论】:
-
对不起,我刚刚注意到一些事情......请参阅下面的答案。
-
是的,我今天早上看了这些例子。我在上面的最佳答案和上面的示例之间看到的唯一功能区别是它们在读取 StandardOutput 和 StandardError 之前调用 WaitForExit,而我在之后调用 WaitForExit。我只是尝试在我的示例中进行更改并重新测试 - 不高兴!
-
是的,我只是注意到您正在尝试在 ASPX / AppPool 上下文中执行此操作......这根本行不通。甚至 cmd.exe 也被视为 UI 应用程序,需要适当的用户上下文才能运行。
-
您是否也应该将
StartInfo.RedirectStandardInput设置为true?
标签: c# batch-file cmd process.start