Foo.cmd不会输出正在处理的行(在网站上)
我在理解.NET中ProcessStartInfo类的in和out时遇到了问题。 我使用这个类来执行像FFmpeg这样的.exe程序,没有任何问题。
但是,当我使用ProcessStartInfo启动.cmd程序时,就像只包含@echo Hello world
的简单foo.cmd一样,它不会输出任何东西。
ProcessStartInfo oInfo = new ProcessStartInfo(@"C:\Program Files (x86)\itms\foo.cmd") { UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, CreateNoWindow = true }; using (Process p = new Process()) { p.StartInfo = oInfo; p.OutputDataReceived += new DataReceivedEventHandler(transporter_OutputDataReceived); p.Start(); p.BeginOutputReadLine(); p.WaitForExit(); } private void transporter_OutputDataReceived(object sender, DataReceivedEventArgs e) { Response.Write(e.Data + " - line
"); }
我见过很多例子,人们使用cmd.exe启动.cmd程序,我试过这个,但没有成功。 该程序只是无限期地加载。
ProcessStartInfo oInfo = new ProcessStartInfo("cmd", "/c start foo.cmd") { UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, CreateNoWindow = true, WorkingDirectory = @"C:\Program Files (x86)\itms" };
在Windows和Mac上使用命令行工具时,foo.cmd程序可以成功运行和输出。
请有人请为我揭开这个神秘面纱。
谢谢
编辑
在本地执行时,代码行为正确。 当我在我们的网站上执行代码时出现问题。 要么不允许执行程序,要么以某种方式禁用输出。
只有cmd.exe返回输出‘“cmd”,“/ c dir”’例如返回有关当前文件夹内容的信息。
这真的是一个许可问题吗?
我自己找到了答案,并会为有兴趣的人发布解决方案。
问题的根源很难调试,因为问题源于IIS处理用户和进程的方式。
正如我所想,代码本身没有任何问题。
回答
在IIS中,网站正在AppPool中运行。 为AppPool分配用户标识。 默认标识是名为ApplicationPoolIdentity的虚拟内置帐户。 此用户没有权限调用任何(据我所知)外部批处理/命令脚本。
在开始新流程时为管理用户提供用户名,密码和域名,并没有为我解决任何问题 – 可能是因为我只是误解了整个概念。
在webconfig中使用
也没有解决任何问题。 这显然是因为指定的AppPool用户仍然是所有进程的作者。
真正让我烦恼的是,我可以执行.exe文件,但不能执行.cmd或.bat文件。
对我来说,解决方案是创建一个具有执行批处理脚本权限的新用户,并选择该用户作为IIS中的AppPool用户。
编辑:正如我在评论中提到的,我正在使用的用户是在Active Directory服务器上创建的,因为此特定文件服务器位于网络共享上。 用户是我的Web服务器上本地服务器组IIS_IUSRS的一部分,并且在存储可执行程序的文件夹中具有读/写/执行权限。
Edit2:该解决方案适用于本地用户帐户,只要用户是本地服务器组IIS_IUSRS的一部分,并且在存储可执行程序的文件夹中具有读/写/执行权限。
这是稍微修改过的代码,但它可以让您更好地了解该类
ProcessStartInfo info = new ProcessStartInfo(); info.Arguments = "/CC:\Program Files (x86)\itms\foo.cmd"; info.WindowStyle = ProcessWindowStyle.Hidden; info.CreateNoWindow = true; info.FileName = "cmd.exe"; // or C:\Program Files (x86)\itms\foo.cmd with no info.Arguments info.UseShellExecute = false; info.RedirectStandardOutput = true; using (Process process = Process.Start(info)) { using (StreamReader reader = process.StandardOutput) { string result = reader.ReadToEnd(); Console.WriteLine(result); } }
这会将cmd窗口的输出重定向到控制台,只需根据需要进行调整。
你需要这样使用它
using (Process p = Process.Start(oInfo)) { .....
原因是因为Process.Start()和Process.Star(startinfo)的工作方式略有不同
Process.Start() – 启动(或重用)由此Process组件的StartInfo属性指定的进程资源,并将其与组件关联。
回报价值
类型:System.Boolean如果启动了进程资源,则为true;否则为false。 如果没有启动新进程资源,则返回false(例如,如果重用现有进程)。
Process.Start(StartInfo) – 启动由包含流程启动信息的参数(例如,要启动的流程的文件名)指定的流程资源,并将资源与新的流程组件相关联。
回报价值
类型:System.Diagnostics.Process与流程资源关联的新Process组件,如果未启动任何流程资源,则为null(例如,如果重用现有流程)。
- 我如何使用ConvertTo-SecureString
- 使用Google Data API使用C#访问Google Spreadsheets会因Mono而失败
- 在实现自己的IUserStore时,类上的“可选”接口实际上是可选的吗?
- System.IO.FileNotFoundException:找不到网络路径。 在Windows 7上使用DirectoryEntry对象时出现exception
- 将DataSet \ DataTable转换为CSV
- 为什么在单击ToolStrip按钮两次时抛出NullReferenceException – openFileDialog.showDialog()?
- 单击背景中的表单时,Datagridview将消失
- 打开发布模式时捆绑不在MVC5中工作
- 如何最好地在.NET中使用XPath和非常大的XML文件?