C# 返回StandardOutput时,appcmd.exe和dnscmd.exe的行为不同
我正在开发的东西应该像一个自我部署应用程序的托管面板一样工作。我创建了一个方法,该方法将文件名和参数作为参数,并在执行时在面板网页上给出输出C# 返回StandardOutput时,appcmd.exe和dnscmd.exe的行为不同,c#,asp.net,iis,dns,windows-server-2012,C#,Asp.net,Iis,Dns,Windows Server 2012,我正在开发的东西应该像一个自我部署应用程序的托管面板一样工作。我创建了一个方法,该方法将文件名和参数作为参数,并在执行时在面板网页上给出输出 // as there will not be an input stream so don't Redirect p.StartInfo.RedirectStandardInput = false; // use a stringbuilder to capture everything
// 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;
这是我的方法
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;
}
}
// 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;
当我使用此方法在IIS上创建站点(使用appcmd.exe)时,我会在命令promt上执行此可执行文件时获得所有输出。但是当涉及到dnscmd.exe在DNS上创建条目时,我什么也得不到!标准输出结果是空的。我使用管理员凭据来执行这些可执行文件。顺便说一下,我现在使用的是Windows Server 2012 Standart。我还没有在Server2008R2上测试这个方法,但我相信结果是一样的
// 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;
对于我来说,看到appcmd和dnscmd可执行文件在同一个方法上表现出不同的行为有些奇怪
// 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;
我在这里错过了什么
// 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;
谢谢
// 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;
编辑:StandardOutput和StandardError都返回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;
编辑2:我将ReadLine()更改为ReadToEnd()。这是我在四处玩耍、尝试时改变的。原始代码具有ReadToEnd()
// 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;
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;
}
}
// 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;
private string ExecuteAppCmd(string sysUser,SecureString SecureString)
{
使用(进程p=新进程())
{
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”和“
”);
返回消息;
}
}
“appcmd list site domain.com”在命令promt上显示domain.com的iis站点配置。如果domain.com不在iis中,则会显示错误。无论哪种方式,都有一个输出,它可以很好地与此代码配合使用
// 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;
这是给dnscmd的。这一个在asp.net页面上执行任务,但不使用StandardOutput显示其输出。但是,输出显示在命令提示符下
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;
}
}
// 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;
private string ExecuteDnsCmd(string sysUser,SecureString SecureString)
{
使用(进程p=新进程())
{
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”和“
”);
返回消息;
}
}
我没有一个可以运行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;
//因为没有输入流,所以不要重定向
p、 StartInfo.RedirectStandardInput=false;
//使用stringbuilder捕获所有内容
var sb=新的StringBuilder();
//在stdout和stderr上引发事件并处理它们
p、 EnableRaisingEvents=true;
p、 OutputDataReceived+=(发送方,args)=>sb.AppendFormat(“输出:{0}
”,args.Data);
p、 ErrorDataReceived+=(发送方,args)=>sb.AppendFormat(“Err:{0}
”,args.Data);
p、 Start();
//开始消费
p、 BeginOutputReadLine();
p、 BeginErrorReadLine();
//等待进程退出
p、 WaitForExit();
p、 Close();
//获取外部stringbuilder值
字符串消息=sb.ToString();
返回消息;
dnscmd可能只写入StandardError。事实上,为了调查是否存在错误,我尝试了StandardError和StandardOutput。我真的应该把它写下来作为评论。但它们都返回空。感谢您的快速响应,顺便说一句:)如果您尝试使用命令提示符dnscmd>output.txt
gets output.txt填充?只需检查:taget服务器安装了DNS服务?因为您只读取第一行,dnscmd的第一行可能是空的吗?我感觉很糟糕。我对这段代码玩得太久了,以至于忘了在main方法中有一个控件检查:(你的代码和我的代码在删除该复选框后都工作正常。我在尝试你的代码时意识到了我的错误。因此,我选择这一个作为答案。但我认为如果你也告诉我你的代码和我的代码是做同一件事的不同方式,应该会更好,除了我的代码给出了在t结尾创建的输出这是一个过程,而你的过程正在捕获过程中的所有输出。我希望我没有弄错。这是正确的!我会在我的回答中反映出来。不要感到尴尬。有时明显的错误很难发现,你需要其他人来弄清楚发生了什么。我很高兴它最终对你起了作用。