appcmd.exe 和 dnscmd.exe在返回 StandardOutput 时的行为不同

本文关键字:exe StandardOutput dnscmd 返回 appcmd | 更新日期: 2023-09-27 18:31:15

我正在开发一些东西,它应该像自部署应用程序的托管面板一样工作。我创建了一个将文件名和参数作为参数的方法,并且在执行时应该在面板网页上给出输出。

这是我的方法;

private string ExecuteCmd(string sysUser, SecureString secureString, string argument, string fileName)
{
    using (Process p = new Process())
    {
        p.StartInfo.FileName = fileName;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.UserName = sysUser;
        p.StartInfo.Password = secureString;
        p.StartInfo.Arguments = argument;
        p.Start();
        p.WaitForExit();
        StreamReader sr = p.StandardOutput;
        p.Close();
        string message = sr.ReadToEnd();
        return message;
    }
}

当我使用此方法在 IIS 上创建站点(使用 appcmd.exe)时,当我在命令 promt 上执行此可执行文件时,我会获得所有输出。但是当涉及到 dnscmd 时.exe要在 DNS 上创建条目,我什么也得不到!标准输出只是空的。我使用管理员凭据来执行这些可执行文件。顺便说一下,我在Windows Server 2012 Standart上。我还没有在Server 2008 R2上测试这种方法,但我相信结果无论如何都是一样的。

看到 appcmd 和 dnscmd 可执行文件在同一方法上的行为不同,这对我来说有点奇怪。

我在这里缺少什么?

谢谢!

编辑:StandardOutput 和 StandardError 都返回 dnscmd.exe 的错误。

编辑2:我将ReadLine()更改为ReadToEnd()。这是我在玩耍、尝试时改变的东西。原始代码具有 ReadToEnd()。

Edit3:带有文件路径和参数的完整方法。这是针对 IIS,它显示输出没有问题;

private string ExecuteAppCmd(string sysUser, SecureString secureString)
{
    using (Process p = new Process())
    {
        p.StartInfo.FileName = @"C:'Windows'System32'inetsrv'APPCMD.EXE";
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        p.StartInfo.UserName = sysUser;
        p.StartInfo.Password = secureString;
        p.StartInfo.Arguments = " list site domain.com";
        p.Start();
        p.WaitForExit();
        StreamReader sr = p.StandardOutput;
        p.Close();
        string message = sr.ReadToEnd().Replace("'n", "<br />");
        return message;
    }
}

"appcmd 列表站点 domain.com"在命令 PROMT 上显示 domain.com 的 IIS 站点配置。如果 domain.com 不在 IIS 中,则会显示错误。无论哪种方式,都有一个输出,并且使用此代码可以正常工作。

这是针对dnscmd的。这个在页面上完成 asp.net 工作,但不显示它与标准输出的输出。但是,输出显示在命令提示符上。

private string ExecuteDnsCmd(string sysUser, SecureString secureString)
{
    using (Process p = new Process())
    {
        p.StartInfo.FileName = @"C:'Windows'System32'DNSCMD.EXE";
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        p.StartInfo.UserName = sysUser;
        p.StartInfo.Password = secureString;
        p.StartInfo.Arguments = " /zoneadd domain.com /primary";
        p.Start();
        p.WaitForExit();
        StreamReader sr = p.StandardError;
        p.Close();
        string message = sr.ReadToEnd().Replace("'n", "<br />");
        return message;
    }
}

appcmd.exe 和 dnscmd.exe在返回 StandardOutput 时的行为不同

我没有一个可以运行dnscmd的盒子.exe但是因为您声称其他一切都有效,我只能想象错误和输出流的处理以某种方式纠缠在一起。如果尝试此代码,唯一的区别是此代码在单独的线程上处理错误流和输出流,并在运行期间收集其输出。如果这有效,您的代码也应该没问题。

        // as there will not be an input stream so don't Redirect 
        p.StartInfo.RedirectStandardInput = false;
        // use a stringbuilder to capture everything
        var sb = new StringBuilder();
        // raise events on stdout and stderr and handle them
        p.EnableRaisingEvents = true;
        p.OutputDataReceived += (sender, args) => sb.AppendFormat("Out: {0}<br />",args.Data);
        p.ErrorDataReceived  += (sender, args) => sb.AppendFormat("Err: {0}<br />",args.Data);
        p.Start();
        // start consuming
        p.BeginOutputReadLine();
        p.BeginErrorReadLine();
        // wait for process to exit
        p.WaitForExit();
        p.Close();
        // obtain out stringbuilder value
        string message = sb.ToString();
        return message;