当前位置: 首页 > 编程语言 > C#

如何在C#中捕获Shell命令输出?分享

时间:2023-04-10 23:37:01 C#

C#中如何捕获shell命令的输出?摘要:完整问题:我需要找到一种在csharp中运行命令行命令并捕获其输出的方法。我知道如何在Perl中执行此操作,下面是我将在Perl中使用的代码。#machine检查我的$pc=$_[0];#createlocationofregistryquerymy$machine="\\".$pc."\HKEY_USERS";#runregistryquerymy@regQuery=`REGQUERY$machine`;欢迎任何有关如何在csharp中执行此操作的建议。到目前为止,我已经尝试使用RegistryKeyOurKey=Registry.Users方法,它工作正常,但我无法查询远程计算机上的注册表。如果您需要更多信息,请联系我们。解决方案:(感谢@Robaticus)privatevoidreg(stringhost){stringbuild="QUERY\\"+host+"\HKEY_USERS";字符串参数=@build;字符串输出=“”;字符串错误=string.Empty;ProcessStartInfopsi=newProcessStartInfo("reg.exe",parms);psi.RedirectStandardOutput=true;psi.RedirectStandardError=true;psi.WindowStyle=System.Diagnostics.ProcessWindowStyle.Normal;psi.UseShellExecute=false;进程注册;reg=System.Diagnostics.Process.Start(psi);使用(System.IO.StreamReadermyOutput=reg.StandardOutput){output=myOutput.ReadToEnd();}使用(System.IO.StreamReadermyError=reg.StandardError){error=myError.ReadToEnd();}Output.AppendText(output+"n");你可能需要稍微调整一下,但这里有一些(从原来的稍微修改过的)代码来重定向stdout和stderrProcess:stringparms=@"QUERY\machineHKEY_USERS";字符串输出=“”;字符串错误=string.Empty;ProcessStartInfopsi=newProcessStartInfo("reg.exe",parms);psi.RedirectStandardOutput=true;psi.Re直接标准错误=真;psi.WindowStyle=System.Diagnostics.ProcessWindowStyle.Normal;psi.UseShellExecute=false;System.Diagnostics.Process注册;reg=System.Diagnostics.Process.Start(psi);使用(System.IO.StreamReadermyOutput=reg.StandardOutput){output=myOutput.ReadToEnd();}使用(System.IO.StreamReadermyError=reg.StandardError){error=myError.ReadToEnd();事实上,任何你可以从命令行运行的内容都可以在具有类似约束的C#程序中运行有几种方法可以做到,一种是通过我在我的博客中展示的异步进程命令。您只需以主动的方式编写和阅读命令行。从这里开始,只需弄清楚您想要完成什么以及如何使用命令行完成它。然后插入到程序中cmd.OutputReceived+=newLaunchCommandAsProcess.OutputEventHandler(launch_OutputReceived);cmd.SendCommand("帮助");命令。SendCommand("ipconfig");cmd.SyncClose();}///从命令提示符输出正常和错误输出。staticvoidlaunch_OutputReceived(objectsendingProcess,EventArgsForCommande){Console.WriteLine(e.OutputData);}}例如,如您所见,您只需实例化类、处理输出事件并开始编写命令,就像在命令提示符下键入命令一样。下面是它的工作原理:publicclassLaunchCommandAsProcess{publicdelegatevoidOutputEventHandler(objectsendingProcess,EventArgsForCommande);公共事件OutputEventHandlerOutputReceived;私人StreamWriter标准输入;私有进程p;publicvoidSendCommand(stringcommand){stdIn.WriteLine(command);}publicLaunchCommandAsProcess(){p=newProcess();p.StartInfo.FileName=@"C:WindowsSystem32cmd.exe";p.StartInfo.UseShellExecute=false;p.StartInfo.RedirectStandardInput=true;p.StartInfo.RedirectStandardOutput=true;p.StartInfo.RedirectStandardError=true;p.StartInfo.CreateNoWindow=true;p.开始();stdIn=p.StandardInput;p.OutputDataReceived+=Process_OutputDataReceived;p.ErrorDataReceived+=Process_OutputDataReceived;p.BeginOutputReadLine();p.BeginErrorReadLine();}//////在接收到输出数据时引发事件。包括正常和错误输出。/////////privatevoidProcess_OutputDataReceived(objectsendingProcess,DataReceivedEventArgsoutLine){if(outLine.Data==null)返回;else{if(OutputReceived!=null){EventArgsForCommande=newEventArgsForCommand();e.OutputData=outLine.Data;OutputReceived(这个,e);}}}//////同步关闭命令提示符。///publicvoidSyncClose(){stdIn.WriteLine("退出");p.WaitForExit();p.关闭();}/////异步关闭命令提示符。///publicvoidAsyncClose(){stdIn.WriteLine("退出");p.关闭();}}publicclassEventArgsForCommand:EventArgs{publicstringOutputData{get;内部设置;这是我正在使用的类。它改编自我刚刚在博客中找到的代码,但进行了各种其他修改。使用系统;使用系统诊断;使用系统文本;使用系统线程;namespaceSonomaTechnologyInc{//////用于使用命令行程序的实用程序类。///publicclassSubprocess{privateSubprocess(){}//////执行命令行程序,指定等待它完成的最长时间。/////////程序可执行文件的路径。/////////程序的命令行参数。/////////等待子进程完成的最长时间,以毫秒为单位。/////////一个包含///运行程序的结果。///publicstaticSubprocessResultRunProgram(stringcommand,stringargs,inttimeout){booltimedOut=false;ProcessStartInfopinfo=newProcessStartInfo(命令);pinfo.Arguments=args;pinfo.UseShellExecute=false;pinfo.CreateNoWindow=true;//pinfo.WorkingDirectory=?pinfo.RedirectStandardOutput=true;pinfo.RedirectStandardError=true;过程esssubprocess=Process.Start(pinfo);ProcessStreamprocessStream=newProcessStream();尝试{processStream.Read(subprocess);subprocess.WaitForExit(超时);processStream.Stop();if(!subprocess.HasExited){//OK,我们一直等到超时但它仍然没有退出;现在就终止进程timedOut=true;尝试{subprocess.Kill();processStream.Stop();}catch{}subprocess.WaitForExit();}}catch(Exceptionex){subprocess.Kill();processStream.Stop();扔前;}最后{processStream.Stop();}TimeSpanduration=subprocess.ExitTime-subprocess.StartTime;floatexecutionTime=(float)duration.TotalSeconds;SubprocessResultresult=newSubprocessResult(executionTime,processStream.StandardOutput.Trim(),processStream.StandardError.Trim(),subprocess.ExitCode,timedOut);返回结果;}}//////表示执行命令行程序的结果。///publicclassSubprocessResult{readonlyfloatexecutionTime;只读字符串标准输出;只读字符串标准错误;只读intexitCode;只读布尔超时;内部SubprocessResult(floatexecutionTime,stringstdout,stringstderr,intexitCode,booltimedOut){this.executionTime=executionTime;this.stdout=标准输出;this.stderr=标准错误;this.exitCode=exitCode;this.timedOut=timedOut;}//////获取子进程花费的总时间,以秒为单位。///publicfloatExecutionTime{get{returnexecutionTime;}}//////获取子进程写入其标准输出流的输出。///公共字符串标准输出{get{返回标准输出;}}//////获取子进程写入其标准错误流的输出。///publicstringStderr{get{returnstderr;}}//////获取子进程的退出代码。///publicintExitCode{get{returnexitCode;}}//////获取一个标志,指示子进程是否因为///超时而中止。///publicboolTimedOut{get{r返回超时;}}}internalclassProcessStream{/**获取进程标准输出/标准错误流的类*作者:SeemabK(seemabk@yahoo.com)*用法://createProcessStreamProcessStreammyProcessStream=newProcessStream();//根据需要创建和填充流程ProcessmyProcess=newProcess();myProcess.StartInfo.FileName="myexec.exe";myProcess.StartInfo.Arguments="-myargs";//重定向标准输出和/或标准错误myProcess.StartInfo.UseShellExecute=false;myProcess.StartInfo.RedirectStandardOutput=true;myProcess.StartInfo.RedirectStandardError=true;//启动进程myProcess.Start();//连接到ProcessStreammyProcessStream.Read(refmyProcess);//等待进程结束myProcess.WaitForExit();//获取捕获的输出:)stringoutput=myProcessStream.StandardOutput;字符串错误=myProcessStream.StandardError;*/privateThreadStandardOutputReader;私有线程StandardErrorReader;私有进程运行进程;私有字符串_StandardOutput="";私有字符串_StandardError="";公共字符串StandardOutput{得到{返回_StandardOutput;}}publicstringStandardError{get{return_StandardError;}}publicProcessStream(){初始化();}publicvoidRead(Processprocess){try{Init();运行过程=进程;如果(RunProcess.StartInfo.RedirectStandardOutput){StandardOutputReader=newThread(newThreadStart(ReadStandardOutput));StandardOutputReader.Start();}if(RunProcess.StartInfo.RedirectStandardError){StandardErrorReader=newThread(newThreadStart(ReadStandardError));StandardErrorReader.Start();}int超时=1*60*1000;//一分钟if(StandardOutputReader!=null)StandardOutputReader.Join(TIMEOUT);如果(StandardErrorReader!=null)StandardErrorReader.Join(TIMEOUT);}catch{}}privatevoidReadStandardOutput(){if(RunProcess==null)返回;尝试{StringBuildersb=newStringBuilder();字符串行=空;同时((行=RunProcess.StandardOutput。}_StandardOutput=sb.ToString();}catch{}}privatevoidReadStandardError(){if(RunProcess==null)返回;尝试{StringBuildersb=newStringBuilder();字符串行=空;while((line=RunProcess.StandardError.ReadLine())!=null){sb.追加(行);某人。追加(环境。换行);}_StandardError=sb.ToString();}catch{}}privatevoidInit(){_StandardError="";_StandardOutput="";运行过程=空;停止();}publicvoidStop(){try{if(StandardOutputReader!=null)StandardOutputReader.Abort();}catch{}try{if(StandardErrorReader!=null)StandardErrorReader.Abort();}catch{}StandardOutputReader=null;StandardErrorReader=null;这没有回答问题,但Registry.OpenRemoteBaseKey方法以与REG命令调用RegistryKey.GetSubKeyNames相同的方式连接到另一台机器的注册表以获得与REGQUERY相同的输出。您可以使用System.Diagnostics.Process类捕获StandardOutput和StandardError。http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx请务必阅读文档的备注部分。必须正确设置进程类的某些属性才能使StandardOutput可用(例如,UseShellExecute必须设置为false)。以上是C#学习教程:如何在C#中捕获Shell命令输出?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: