我创建了一个通用类来执行控制台应用程序,同时将其输出重定向到我的表单中的
RichTextBox
。
代码工作得很好,但是
Process.Exited
事件永远不会触发,即使控制台应用程序在完成其功能后正常存在。
此外,
WaitForExit
这是课程(更新):
using System;
using System.Diagnostics;
public class ConsoleProcess
{
private string fpath;
public ConsoleProcess(string filePath)
{
fpath = filePath;
}
public void Run(string arguments)
{
var procInfo = new ProcessStartInfo()
{
FileName = fpath,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
var proc = new Process() { EnableRaisingEvents = true, StartInfo = procInfo };
proc.OutputDataReceived += Proc_DataReceived;
proc.ErrorDataReceived += Proc_DataReceived;
proc.Exited += Proc_Exited;
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
}
public event EventHandler<EventArgs>? ProcessExited;
private void Proc_Exited(object? sender, EventArgs e)
{
ProcessExited?.Invoke(sender, e);
}
public event EventHandler<DataReceivedEventArgs>? DataReceived;
private void Proc_DataReceived(object sender, DataReceivedEventArgs e)
{
DataReceived?.Invoke(sender, e);
}
}
这是我在
Form
中使用的代码:
ConsoleProcess process = new("console_app.exe");
process.DataReceived += Process_DataReceived;
process.ProcessExited += Process_Exited;
private async void Execute()
{
await Task.Run(() =>
{
process.Run("--arguments");
});
}
private void Process_DataReceived(object? sender, System.Diagnostics.DataReceivedEventArgs e)
{
//do stuff
}
private void Process_Exited(object? sender, EventArgs e)
{
MessageBox.Show("Done");
}
PS:我知道有几个关于这个问题的帖子,我已经检查过它们,但没有一个有帮助,所以我在这里。
要解决您面临的问题,请尝试添加
proc.WaitForExit();
。
代码:
...
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
//added - wait for exit
proc.WaitForExit();
...
如果您想使用
Task
,请尝试以下操作:
注意:我将类
ConsoleProcess
重命名为HelperProcess
,因为原来的名称似乎有些欺骗性。
创建新项目 - Windows 窗体应用程序
ProcessTest
.NET 5
创建一个类(名称:HelperProcess.cs)
辅助进程:
using System;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ProcessTest
{
public class HelperProcess
{
public event EventHandler<EventArgs> ProcessExited;
public event EventHandler<DataReceivedEventArgs> DataReceived;
private string fPath;
public HelperProcess(string filePath)
{
fPath = filePath;
}
public async Task Run(string arguments)
{
Debug.WriteLine($"fPath: {fPath}");
var procInfo = new ProcessStartInfo()
{
FileName = fPath,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
using (Process proc = new Process() { EnableRaisingEvents = true, StartInfo = procInfo })
{
//subscribe to events
proc.OutputDataReceived += Proc_DataReceived;
proc.ErrorDataReceived += Proc_DataReceived;
proc.Exited += Proc_Exited;
//start
proc.Start();
//start reading
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
//Debug.WriteLine("before proc.WaitForExitAsync");
//wait for exit
await proc.WaitForExitAsync();
//Debug.WriteLine("after proc.WaitForExitAsync");
//unsubscribe from events
proc.OutputDataReceived -= Proc_DataReceived;
proc.ErrorDataReceived -= Proc_DataReceived;
proc.Exited -= Proc_Exited;
}
}
private void Proc_Exited(object sender, EventArgs e)
{
//Debug.WriteLine("Proc_Exited");
ProcessExited?.Invoke(sender, e);
}
private void Proc_DataReceived(object sender, DataReceivedEventArgs e)
{
//ToDo: add desired code
//Debug.WriteLine($"Proc_DataReceived: {e.Data}");
//if (DataReceived != null && !String.IsNullOrEmpty(e.Data))
//{
// DataReceived.Invoke(sender, e);
//}
DataReceived?.Invoke(sender, e);
}
}
}
向 Form1 添加按钮(名称:btnRun)
Click
事件处理程序打开属性窗口
向 Form1 添加
FormClosed
事件处理程序
表格1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace ProcessTest
{
public partial class Form1 : Form
{
private HelperProcess _process = null;
public Form1()
{
InitializeComponent();
string fPath = string.Empty;
//environment variable windir has the same value as SystemRoot
//use 'Sysnative' to access 64-bit files (in System32) if program is running as 32-bit process
//use 'SysWow64' to access 32-bit files on 64-bit OS
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
fPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "Sysnative", "wbem", "wmic.exe");
else
fPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "wbem", "wmic.exe");
//create new instance
_process = new HelperProcess(fPath);
//subscribe to events
_process.DataReceived += Process_DataReceived;
_process.ProcessExited += Process_ProcessExited;
}
private async void btnRun_Click(object sender, EventArgs e)
{
Debug.WriteLine("before Execute");
await Execute();
Debug.WriteLine("after Execute");
}
private async Task Execute()
{
await _process.Run("process get");
Debug.WriteLine("after _process.Run");
}
private void Process_ProcessExited(object sender, EventArgs e)
{
Debug.WriteLine("Main: Process_ProcessExited");
}
private void Process_DataReceived(object sender, DataReceivedEventArgs e)
{
Debug.WriteLine($"Main: Process_DataReceived: {e.Data}");
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (_process != null)
{
//unsubscribe from events
_process.DataReceived -= Process_DataReceived;
_process.ProcessExited -= Process_ProcessExited;
}
}
}
}
资源: