【问题标题】:Process.Start cmd.exe won't run cmd file that is passed as agument when running in IISProcess.Start cmd.exe 在 IIS 中运行时不会运行作为 agument 传递的 cmd 文件
【发布时间】: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


【解决方案1】:

不使用“cmd”怎么办?

Process proc = new Process ();
proc.StartInfo.FileName = @"c:\mypath\myfile.cmd";

【讨论】:

  • 如果 UseShellExecute 为 true,则有效,但我需要 UseShellExecute = false 才能从 cmd 文件中获取响应。
【解决方案2】:

从 ASPX 页面运行批处理文件或任何进程都是徒劳的,因为 IIS 不在真正的 Windows 用户上下文下运行。因此,无论您为运行 AppPool 的用户提供了多少设置和权限,或者您进行了任何类型的配置更改,它都将永远无法正常工作。我很久以前也遇到过同样的问题,基本上是不可能的。

在此处查看我以前的问题(和 cmets),以及针对您当前问题的可能“概念”解决方案的公认答案:

Process.Start won't work

【讨论】:

  • 当。我还尝试使用 cscript.exe 运行一个测试,将它传递给一个 js 脚本文件,它也不会对此做任何事情,所以它不是 exe.cmd 特定的。我觉得有趣的是,在这种情况下,“某些”事情确实可以成功运行:-我原来的选项 1 与 cmd.exe 一起工作。正如@Derek 所提到的,我也可以直接提供 cmd 文件作为文件名和 UseShellExecute = true,这也确实有效,尽管我无法以这种方式得到响应。我想我可以按照 Derek 的方式运行它,让 cmd 将响应写入文件,然后用 c# 读取文件,但这很丑!
  • 是的,我知道...有一些奇怪的东西对我有用,也对我没用!它确实很难看......我不得不做一些非常时髦的事情来让我的进程也能正常工作......我不得不在一个文本文件中写一些东西,并让一个在后台运行的 Windows 服务来获取它(那个文件已更改)然后从 Windows 服务启动应用程序,而不是在我自己的帐户下并唤醒 PC 和各种奇怪的事情,只是为了能够从网页上启动我的进程......它确实很糟糕。
  • 感谢您的帮助 - 您的意见让我找到了解决方案!用解决方案更新了我原来的问题。
  • 太棒了! :) 很高兴它在某种程度上有所帮助:)
  • 我可能是错的,但我认为也许我上面的“RunMyCmdAndGetResponse”解决方案也可以运行您的 exe 文件,就像您在发布的链接中尝试的那样。您只需将其传递给您的 exe 文件的路径,而不是传递给 cmd 文件的路径。当然假设您的 exe 文件没有 UI 组件等。
猜你喜欢
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 2017-09-11
  • 2017-08-14
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多