process.start:如何获取输出?
-
28-09-2019 - |
题
我想从我的单声道/.NET应用程序运行外部命令行程序。例如,我想运行 Mencoder. 。是否可以:
- 要获取命令行壳输出,然后将其写入我的文本框上?
- 要获得数值以显示出时间的进度标准?
解决方案
当您创建您的 Process
对象集 StartInfo
适当:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "program.exe",
Arguments = "command line arguments to your executable",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
然后开始过程并从中读取:
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
// do something with line
}
您可以使用 int.Parse()
或者 int.TryParse()
将字符串转换为数字值。如果您阅读的字符串中有无效的数字字符,则可能必须先进行一些字符串操作。
其他提示
您可以处理输出 同步 或者 异步.
1:同步示例
static void runCommand()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR"; // Note the /c command (*)
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
//* Read the output (or the error)
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
string err = process.StandardError.ReadToEnd();
Console.WriteLine(err);
process.WaitForExit();
}
笔记 最好处理两者 输出 和 错误: :必须单独处理。
(*)对于某些命令(此处 StartInfo.Arguments
)您必须添加 /c
指示, ,否则该过程在 WaitForExit()
.
2:异步示例
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
//* Start process and handlers
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
如果您不需要使用输出进行复杂的操作,则可以绕过Outputhandler方法,只需直接添加处理程序:
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
好吧,对于任何想要读取错误和输出的人,但使用其他答案(例如我)提供的任何解决方案都会陷入僵局,这是我在阅读MSDN解释后构建的解决方案。
答案基于T30的代码:
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set ONLY ONE handler here.
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
//* Start process
process.Start();
//* Read one element asynchronously
process.BeginErrorReadLine();
//* Read the other one synchronously
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
这样做的标准.NET方法是从过程中阅读' 标准输出 溪流。链接的MSDN文档中有一个示例。类似,您可以从中阅读 Standarderror, ,并写信给 StandardInput.
如下所述,可以获取过程的命令行壳输出: http://www.c-sharpcorner.com/uploadfile/edwinlima/systemdiagnosticprocess12052005035444AM/systemdiastemdiagnosticprocess.aspx
这取决于Mencoder。如果它在命令行上输出此状态,则是:)
您可以使用共享内存进行两个过程进行通信,请查看 MemoryMappedFile
您将主要创建一个内存映射的文件 mmf
在使用“使用”语句的父进程中,然后创建第二个过程,直到终止并将结果写入 mmf
使用 BinaryWriter
, ,然后阅读从 mmf
使用父进程,您也可以通过 mmf
使用命令行参数或硬代码的名称。
确保在您制作子进程的父进程中使用映射的文件时,将结果写入映射的文件,然后在父进程中释放映射文件之前
示例:父进程
private static void Main(string[] args)
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("memfile", 128))
{
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(512);
}
Console.WriteLine("Starting the child process");
// Command line args are separated by a space
Process p = Process.Start("ChildProcess.exe", "memfile");
Console.WriteLine("Waiting child to die");
p.WaitForExit();
Console.WriteLine("Child died");
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader reader = new BinaryReader(stream);
Console.WriteLine("Result:" + reader.ReadInt32());
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
儿童过程
private static void Main(string[] args)
{
Console.WriteLine("Child process started");
string mmfName = args[0];
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(mmfName))
{
int readValue;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader reader = new BinaryReader(stream);
Console.WriteLine("child reading: " + (readValue = reader.ReadInt32()));
}
using (MemoryMappedViewStream input = mmf.CreateViewStream())
{
BinaryWriter writer = new BinaryWriter(input);
writer.Write(readValue * 2);
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
要使用此示例,您需要创建一个带有2个项目的解决方案,然后从%childdir%/bin/debug中获取子进程的构建结果,然后将其复制到%parentdirectory%/bin/debug,然后运行父项目
childDir
和 parentDirectory
PC上的项目的文件夹是好运的:)
如何启动流程(例如BAT文件,Perl脚本,控制台程序),并在Windows表单上显示其标准输出:
processCaller = new ProcessCaller(this);
//processCaller.FileName = @"..\..\hello.bat";
processCaller.FileName = @"commandline.exe";
processCaller.Arguments = "";
processCaller.StdErrReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.StdOutReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.Completed += new EventHandler(processCompletedOrCanceled);
processCaller.Cancelled += new EventHandler(processCompletedOrCanceled);
// processCaller.Failed += no event handler for this one, yet.
this.richTextBox1.Text = "Started function. Please stand by.." + Environment.NewLine;
// the following function starts a process and returns immediately,
// thus allowing the form to stay responsive.
processCaller.Start();
你可以找到 ProcessCaller
在此链接上: 启动过程并显示其标准输出
在Win和Linux中为我工作的解决方案是毛病
// GET api/values
[HttpGet("cifrado/{xml}")]
public ActionResult<IEnumerable<string>> Cifrado(String xml)
{
String nombreXML = DateTime.Now.ToString("ddMMyyyyhhmmss").ToString();
String archivo = "/app/files/"+nombreXML + ".XML";
String comando = " --armor --recipient bibankingprd@bi.com.gt --encrypt " + archivo;
try{
System.IO.File.WriteAllText(archivo, xml);
//String comando = "C:\\GnuPG\\bin\\gpg.exe --recipient licorera@local.com --armor --encrypt C:\\Users\\Administrador\\Documents\\pruebas\\nuevo.xml ";
ProcessStartInfo startInfo = new ProcessStartInfo() {FileName = "/usr/bin/gpg", Arguments = comando };
Process proc = new Process() { StartInfo = startInfo, };
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.Start();
proc.WaitForExit();
Console.WriteLine(proc.StandardOutput.ReadToEnd());
return new string[] { "Archivo encriptado", archivo + " - "+ comando};
}catch (Exception exception){
return new string[] { archivo, "exception: "+exception.ToString() + " - "+ comando };
}
}
您可以使用以下代码记录进程:
ProcessStartInfo pinfo = new ProcessStartInfo(item);
pinfo.CreateNoWindow = false;
pinfo.UseShellExecute = true;
pinfo.RedirectStandardOutput = true;
pinfo.RedirectStandardInput = true;
pinfo.RedirectStandardError = true;
pinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
var p = Process.Start(pinfo);
p.WaitForExit();
Process process = Process.Start(new ProcessStartInfo((item + '>' + item + ".txt"))
{
UseShellExecute = false,
RedirectStandardOutput = true
});
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
if (process.ExitCode != 0) {
}