首页 文章

Foo.cmd不会输出正在处理的行(在网站上)

提问于
浏览
8

我在理解.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程序可以成功运行和输出 .

有人可以请我揭开这个神秘面纱 .

谢谢

EDIT

在本地执行时,代码行为正确 . 当我在我们的网站上执行代码时出现问题 . 要么不允许执行程序,要么以某种方式禁用输出 .

只有cmd.exe返回输出 ´"cmd", "/c dir"´ 例如返回有关当前文件夹内容的信息 .

这实际上是一个许可问题吗?

3 回答

  • 0

    我自己找到了答案,并会为有兴趣的人发布解决方案 .

    问题的根源很难调试,因为问题起源于IIS处理用户和进程的方式 .

    正如我所想,代码本身没有任何问题 .

    Answer

    在IIS中,网站正在AppPool中运行 . 为AppPool分配了用户标识 . 默认标识是名为 ApplicationPoolIdentity 的虚拟内置帐户 . 此用户没有权限调用任何(据我所知)外部批处理/命令脚本 .

    在开始新流程时为管理用户提供用户名,密码和域名,并没有为我解决任何问题 - 可能是因为我只是误解了整个概念 .

    在webconfig中使用 <identity impersonate="true" userName="domain\user" password="pass" /> 也没有解决任何问题 . 这显然是因为指定的AppPool用户仍然是所有进程的作者 .

    真正让我烦恼的是,我可以执行.exe文件,但不能执行.cmd或.bat文件 .

    The solution for me, was to create a new user with privileges to execute batch scripts and select that user as the AppPool user in IIS.

    编辑:正如我在评论中提到的,我正在使用的用户是在 Active Directory 服务器上创建的,因为此特定文件服务器位于网络共享上 . 用户是我的Web服务器上本地服务器组 IIS_IUSRS 的一部分,并且在存储可执行程序的文件夹中具有读/写/执行权限 .

    Edit2:该解决方案适用于本地用户帐户,只要用户是本地服务器组 IIS_IUSRS 的一部分,并且在存储可执行程序的文件夹中具有读/写/执行权限 .

  • 0

    这是稍微修改过的代码,但它可以让你更好地了解这个类

    ProcessStartInfo info = new ProcessStartInfo(); 
    info.Arguments = "/C C:\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窗口的输出重定向到控制台,只需根据需要进行调整 .

  • 14

    你需要这样使用它

    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(例如,如果重用现有进程) .

相关问题