我想从我的Mono/.NET应用程序运行外部命令行程序.例如,我想运行mencoder.可能吗:
我需要生成一个作为控制台应用程序的子进程,并捕获其输出.
我为方法编写了以下代码:
string retMessage = String.Empty;
ProcessStartInfo startInfo = new ProcessStartInfo();
Process p = new Process();
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = command;
startInfo.FileName = exec;
p.StartInfo = startInfo;
p.Start();
p.OutputDataReceived += new DataReceivedEventHandler
(
delegate(object sender, DataReceivedEventArgs e)
{
using (StreamReader output = p.StandardOutput)
{
retMessage = output.ReadToEnd();
}
}
);
p.WaitForExit();
return retMessage;
Run Code Online (Sandbox Code Playgroud)
但是,这不会返回任何内容.我不相信该OutputDataReceived事件被回调,或者该WaitForExit()命令可能阻塞该线程,因此它永远不会回调.
有什么建议?
编辑:看起来我在回调中努力了.这样做:
return p.StandardOutput.ReadToEnd();
Run Code Online (Sandbox Code Playgroud)
似乎工作正常.
我正在尝试启动一个进程并捕获输出,已经走了很远的路,但我还没有达到我想要的解决方案.
具体来说,我试图从我正在编写的小型实用程序应用程序重置我的开发机器上的IIS.我通过实验得出结论,安全的方法是通过iisreset.exe在子进程中运行.
如果iisreset.exe在命令提示符下运行,则会在此过程中收到反馈.运行iisreset需要几秒钟,并且会生成几行反馈,其间会有暂停.
我想捕获这些反馈并将其呈现在我的Windows窗体应用程序中(在a中ListBox),我已经成功了.我仍然担心的是,在子进程完成之前我不会得到它.我想在创建行时立即逐行获取子进程的输出.
我曾尝试做我的作业,阅读/测试例如:
还有几个内容相似的.大多数(全部?)异步获取输出(例如Process.ReadToEnd()).我希望输出同步,根据MSDN文档涉及建立一个事件处理程序等我已经尝试过.它可以工作,但在进程退出之前不会调用事件处理程序.我从iisreset.exe获取输出,但直到它完成.
为了排除这与iisreset.exe特别有关的可能性,我写了一个小的控制台应用程序,它生成一些输出,暂停之间:
namespace OutputGenerator
{
class Program
{
static void Main(string[] args)
{
System.Console.WriteLine("OutputGenerator starting and pausing for 10 seconds..");
System.Threading.Thread.Sleep(10000);
System.Console.WriteLine("Pausing for another 10 seconds..");
System.Threading.Thread.Sleep(10000);
System.Console.WriteLine("Exiting!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
用这个测试结果证明我在需要时可以直接获取捕获的数据.因此,在某种程度上,似乎iisreset.exe输出数据的方式在这里发挥作用.
以下是执行捕获的程序代码(Windows窗体应用程序):
using System;
using System.Windows.Forms;
using System.Diagnostics;
namespace OutputCapturer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnRun_Click(object sender, EventArgs e)
{
// Running this …Run Code Online (Sandbox Code Playgroud) 我有一个第三方DOS进程,它将有关其进度的数据写入命令行.我想对进展做出反应.通常我会用一个Process带RedirectStandardOutput = true和RedirectStandardError = true再
.OutputDataReceived +=xyzOutputDataReceived;
.ErrorDataReceived += xyzErrorDataReceived;
.Start();
.BeginOutputReadLine();
.BeginErrorReadLine();
Run Code Online (Sandbox Code Playgroud)
通常这是有效的.我得到了我需要的DataReceivedEventArg.
在这种情况下,该过程似乎更新了它所写的相同行(这怎么可能?),因此它将15%,15%的更改写入18%,依此类推.只有在执行结束时,似乎才将数据刷新到StandardOutput.
此外,如果我只是尝试将数据传输到文本文件(例如odb.exe >> output.txt),它什么都不显示.
有没有办法获取临时数据?
问题不在于获得标准输出,这可以正常工作(同步和异步).它是关于如何从一个我无法改变的进程中获取输出,并且似乎没有将它的输出刷新到标准流.
与此问题类似,除了在WPF应用程序中包含的控制台程序产生彩色输出,因此如果我可以捕获颜色和文本,那将是很好的.
这是我的第一个WPF程序,我不知道如何去寻找/修改正确的控件,目前我只是使用一个可以工作但只能捕获纯文本的TextBox.
更新:我尝试使用RichTextBox:
richTextBox.Document.Blocks.Clear();
richTextBox.Document.Blocks.Add(new Paragraph(new Run(process.StandardOutput.ReadToEnd())));
Run Code Online (Sandbox Code Playgroud)
唉它只显示了纯文本.
我想用C#获取字符串中的视频文件持续时间.我搜索了互联网,我得到的是:
ffmpeg -i inputfile.avi
Run Code Online (Sandbox Code Playgroud)
而且每个人都说要解析输出的持续时间.
这是我的代码
string filargs = "-y -i " + inputavi + " -ar 22050 " + outputflv;
Process proc;
proc = new Process();
proc.StartInfo.FileName = spath;
proc.StartInfo.Arguments = filargs;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.RedirectStandardOutput = false;
try
{
proc.Start();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
try
{
proc.WaitForExit(50 * 1000);
}
catch (Exception ex)
{ }
finally
{
proc.Close();
}
Run Code Online (Sandbox Code Playgroud)
现在请告诉我如何保存输出字符串并在视频持续时间内解析它.
感谢致敬,
是否可以运行任何基于命令行的程序或批处理文件和捕获器(重定向)输出到文本框LIVE
CL需要时间并产生文本!
类似于tracert.exe(需要时间并产生大量文本).
实际上我将使用tracert.exe,我喜欢实时捕获输出并在运行时在文本框中显示它
编辑:我的问题是让它生活我的意思是控制台产生的任何新行或字符将被发送/拉到/由textBox,直到程序完成!
我想构建的就像这个http://www.codeproject.com/KB/threads/redir.aspx (查看演示),但在C#中
这是我的代码:
private void button1_Click(object sender, EventArgs e)
{
Process pc = new Process();
pc.StartInfo.FileName = "tracert.exe";
pc.StartInfo.Arguments = "google.com";
pc.StartInfo.UseShellExecute = false;
pc.StartInfo.RedirectStandardOutput = true;
pc.StartInfo.CreateNoWindow = true;
pc.Start();
richTextBox1.Text = pc.StandardOutput.ReadToEnd();
pc.WaitForExit();
}
Run Code Online (Sandbox Code Playgroud)
编辑
在你的帮助下(非常感谢)和这个链接:http: //msdn.microsoft.com/query/dev10.query?appId = Dev10IDEF1&l = EN-US&k = k%28EHINVALIDOPERATION.WINFORMS.ILLEGALCROSSTHREADCALL%29; k% 28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV2.0%22%29; K-%28DevLang-CSHARP%29&RD =真
我用这段代码解决了(你认为它没问题吗?):
namespace GUIforCL2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Process _cmd;
delegate void SetTextCallback(string text);
private …Run Code Online (Sandbox Code Playgroud) 我有一个控制台程序,我想不断将Console.Write的结果镜像到一个集合,我可以实时查看它的尾部.集合可以是数组,列表等.
我假设我必须使用某种事件处理程序?
我不介意被指向第三方库的方向,例如NLog.
更新
我需要在内存中维护一个集合,它反映当前的控制台状态(然后我可以使用套接字发送到远程WinForms应用程序).除了细节之外,我想我可以用几行C#来做到这一点 - 我不想添加一个巨大的日志库而不需要它.
我正在尝试制作一个控制台应用程序,它可以包含几乎任何打开控制台的应用程序。
一些简单的事实:
这是我到目前为止所拥有的,除了最后几行之外,一切正常:
ProcessStartInfo startInfo = new ProcessStartInfo("someBatchThingy.cmd");
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.UseShellExecute = false;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
Thread.Sleep(5000);
Stream s = Console.OpenStandardOutput();
byte[] stopCommand = new byte[] { 115, 116, 111, 112, 13 };
s.Write(stopCommand, 0, stopCommand.Length);
process.WaitForExit();
Run Code Online (Sandbox Code Playgroud)
因为性能非常重要,所以我真的想重新分配到进程输出的位置,而不是手动将数据从隐藏控制台传输到包装器控制台。
有谁知道如何做到这一点/如果可能的话?
我一直在忙着编写一个充当前端的应用程序:它有一个GUI,带有按钮等命令行选项,并将它们传递给命令行.exe.它使用应用程序的控制台来显示命令行应用程序的输出.这很好用,但是当使用Ctrl + C或尝试关闭控制台窗口时,GUI也会关闭,这不是我想要的.但是,让程序输出自己的控制台是不可能的,因为它批处理文件,每个文件都会弹出它自己的控制台.
该程序使用MSVC 2012以C++编写,并使用.NET.我试过Console :: CancelKeyPress至少得到Ctrl + C的行为,因为我想要它(停止命令行应用程序,但不是GUI),但有一些麻烦.
我的代码
private: System::Void OnCancelKeyPressed(System::Object^ sender, System::ConsoleCancelEventArgs^ e) {
e->Cancel = true;
}
private: System::Void GetConsoleReady() {
COORD c;
FreeConsole();
AllocConsole();
c.X = 80; c.Y = 8000;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),c);
Console::Clear();
Console::TreatControlCAsInput = false;
Console::CancelKeyPress +=
gcnew ConsoleCancelEventHandler(this, &Form1::OnCancelKeyPressed);
}
Run Code Online (Sandbox Code Playgroud)
每次用户尝试运行要处理的批处理文件时,都会调用此方法.运行批处理后,控制台随FreeConsole()一起发布.第一次它运行良好并使用Ctrl + C杀死命令行应用程序,但GUI中的处理继续,运行其他命令,最后使用FreeConsole().但是,当第二次尝试这样做时,它也会杀死GUI.我尝试在添加新事件之前添加此项以删除上一个事件
Console::CancelKeyPress -=
gcnew ConsoleCancelEventHandler(this, &Form1::OnCancelKeyPressed);
Run Code Online (Sandbox Code Playgroud)
但不知何故,这会在添加处理程序时引发错误,但只是第二次:mscorlib.dll中出现未处理的类型'System.IO.IOException'异常,附加信息:De参数是onjuist.
最后一部分是荷兰语的"错误论证",而调试人员说它在读取ConsoleCancelEventHandler时会窒息.
如果我尝试通过在加载表单时添加它只添加一次事件处理程序,它什么都不做.
这里发生了什么?
c# ×9
.net ×6
.net-4.0 ×1
asp.net ×1
c#-4.0 ×1
c++-cli ×1
command-line ×1
ffmpeg ×1
io ×1
mono ×1
process ×1
spawning ×1
visual-c++ ×1
wpf ×1
wpf-controls ×1