有一个这样的exe文件,起来之后长这个样子:
控制台进程
然后我写了个WinForm程序,通过调用这个exe进行处理,长这样:
我想通过WinForm程序启动这个exe文件,并获取到它的进程对象。因为它这个是控制台应用,所以我能拿到黑窗口里输出的内容,并显示在界面右侧的状态里。
启动exe,获取到进程对象之后,由于这个进程处理时间比较长,会一直阻塞界面,界面卡死不响应操作;放线程中启动这个exe,并获取进程对象,则会有异常“System.InvalidOperationException”类型的未经处理的异常在 System.dll 中发生 StandardError 尚未重定向。
要获取到进程在控制台的输出
public class ProcessUtils
{
private const string exeName = "./realesrgan-ncnn-vulkan.exe";
private const string exeParam = " -i \"{0}\" -o \"{1}\" -n {2}";
/// <summary>
/// 启动进程进行图片的处理
/// </summary>
/// <param name="inputFile">输入图片的路径</param>
/// <param name="outPutFile">输出图片的路径</param>
/// <returns>进程对象</returns>
public static Process ProcessImage(string inputFile, string outPutFile, string param)
{
Process process = new Process();
process.StartInfo.FileName = Path.GetFullPath(exeName);
string parameter = string.Format(exeParam, inputFile, outPutFile, param);
process.StartInfo.Arguments = parameter;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;// 将控制台输出重定向,可以通过进程对象来获取到黑窗口中的输出
process.Start();
return process;
}
}
private void StartClearPicture(object sender, EventArgs e)
{
string inputDir = InputDirTextbox.Text.Trim();
string outputDir = OutPutDirTextbox.Text.Trim();
string param = NormalRadioBtn.Checked ? NormalRadioBtn.Tag.ToString() : AnimeRadioBtn.Tag.ToString();
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
if (!outputDir.EndsWith(@"\"))
{
outputDir+=@"\";
}
ListView.ListViewItemCollection items = this.fileList.Items;
Process process = null;
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
string filename = item.Text;
//Process process = ProcessUtils.ProcessImage(item.Tag.ToString(), outputDir + filename, param);//这样写卡UI,界面必须等进程执行完才会响应用户操作
process = StartProcess(item, outputDir, filename, param);//启动线程并拿到进程对象,这样写会有异常 “System.InvalidOperationException”类型的未经处理的异常在System.dll 中发生 StandardError 尚未重定向。
ShowProgress(item, process);//展示处理进度
process.WaitForExit();//等待当前进程处理完退出后处理下一条
}
}
/// <summary>
/// 启动进程
/// </summary>
/// <param name="item">界面中的一条</param>
/// <param name="outputDir">输出目录</param>
/// <param name="filename">输入文件名</param>
/// <param name="param">进程的参数</param>
/// <returns>进程对象</returns>
private Process StartProcess(ListViewItem item,string outputDir,string filename,string param)
{
Process process = new Process();
new Thread(() =>
{
process = ProcessUtils.ProcessImage(item.Tag.ToString(), outputDir + filename, param);
while (!process.Responding)//等进程有响应再返回进程对象
{
Thread.Sleep(100);
}
}).Start();
return process;
}
/// <summary>
/// 显示处理进度
/// </summary>
/// <param name="item">界面的一条数据</param>
/// <param name="process">进程对象</param>
private void ShowProgress(ListViewItem item,Process process)
{
new Thread(() => {
StreamReader standardError = process.StandardError;
while (!process.HasExited)
{
while(!standardError.EndOfStream){
string str = standardError.ReadLine();
Console.WriteLine(str);//这里是可以拿到黑窗口的输出
this.BeginInvoke(new MethodInvoker(() => { SetProgress(item, str); }));
}
}
this.BeginInvoke(new MethodInvoker(() => { SetProgress(item, "100%"); }));
standardError.Close();
}).Start();
}
/// <summary>
/// 改界面内容
/// </summary>
/// <param name="item">在处理的那一条</param>
/// <param name="str">要改的内容</param>
private void SetProgress(ListViewItem item, string str)
{
item.SubItems[2].Text = str;
if (str.Contains("100%"))
{
item.BackColor = Color.FromArgb(ComponentColor.LightGreen);
}
}
卡界面是因为这句话process.WaitForExit();//等待当前进程处理完退出后处理下一条