我有一个WPF应用程序,它使用Process.Start(ProcessStartInfo info)
启动一个新进程。
如何获取流程的组进程ID,以便我可以使用GenerateConsoleCtrlEvent
发送 Ctrl + C 信号? https://msdn.microsoft.com/en-us/library/windows/desktop/ms683155%28v=vs.85%29.aspx
但是,我似乎无法在创建的新进程中找到控制台窗口的组进程ID。它具有cur窗口用户的会话ID和进程ID。
编辑:我终于得到了我的计划,但我仍然没有找到真正问题的真实答案。
我能够通过使用GenerateConsoleCtrlEvent向控制台中的所有进程广播来将ctrl c发送到进程。
但是,我无法弄清楚如何获取正在运行的进程的进程组。如果创建新进程,您当然可以保存进程组(它应该是使用create new process group的creation标志调用createprocess的进程的ID)。但是,如果您不是自己创建一个新组并且只是想知道一个进程所属的组,我找不到与实际获取此ID相关的任何内容。当然,这些信息存储在某处,可以检索!
我可以使用此函数获取Windows NT版本中的父ID: Fetching parent process Id from child process
但是,这并不能保证同一个流程组。我开始得出结论,Windows没有从进程ID函数获取进程组ID。
Linux有一个简单的getpgrp函数,它确实需要我。我不明白为什么Windows有一个进程组,如果我无法获得它的价值
答案 0 :(得分:1)
GenerateConsoleCtrlEvent
州的文件(强调我的):
接收信号的进程组的标识符。在对CreateProcess函数的调用中指定CREATE_NEW_PROCESS_GROUP标志时,将创建进程组。 新流程的流程标识符也是新流程组的流程组标识符。
因此,如果您的进程位于组中,则WPF应用程序的PID应为组ID。
答案 1 :(得分:0)
我没有使用GenerateConsoleCtrlEvent,而是找到了将CTRL-C发送到进程的方法。仅供参考,在这种情况下,我并不需要找到组进程ID。
using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public class ConsoleAppManager
{
private readonly string appName;
private readonly Process process = new Process();
private readonly object theLock = new object();
private SynchronizationContext context;
private string pendingWriteData;
public ConsoleAppManager(string appName)
{
this.appName = appName;
this.process.StartInfo.FileName = this.appName;
this.process.StartInfo.RedirectStandardError = true;
this.process.StartInfo.StandardErrorEncoding = Encoding.UTF8;
this.process.StartInfo.RedirectStandardInput = true;
this.process.StartInfo.RedirectStandardOutput = true;
this.process.EnableRaisingEvents = true;
this.process.StartInfo.CreateNoWindow = true;
this.process.StartInfo.UseShellExecute = false;
this.process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
this.process.Exited += this.ProcessOnExited;
}
public event EventHandler<string> ErrorTextReceived;
public event EventHandler ProcessExited;
public event EventHandler<string> StandartTextReceived;
public int ExitCode
{
get { return this.process.ExitCode; }
}
public bool Running
{
get; private set;
}
public void ExecuteAsync(params string[] args)
{
if (this.Running)
{
throw new InvalidOperationException(
"Process is still Running. Please wait for the process to complete.");
}
string arguments = string.Join(" ", args);
this.process.StartInfo.Arguments = arguments;
this.context = SynchronizationContext.Current;
this.process.Start();
this.Running = true;
new Task(this.ReadOutputAsync).Start();
new Task(this.WriteInputTask).Start();
new Task(this.ReadOutputErrorAsync).Start();
}
public void Write(string data)
{
if (data == null)
{
return;
}
lock (this.theLock)
{
this.pendingWriteData = data;
}
}
public void WriteLine(string data)
{
this.Write(data + Environment.NewLine);
}
protected virtual void OnErrorTextReceived(string e)
{
EventHandler<string> handler = this.ErrorTextReceived;
if (handler != null)
{
if (this.context != null)
{
this.context.Post(delegate { handler(this, e); }, null);
}
else
{
handler(this, e);
}
}
}
protected virtual void OnProcessExited()
{
EventHandler handler = this.ProcessExited;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
protected virtual void OnStandartTextReceived(string e)
{
EventHandler<string> handler = this.StandartTextReceived;
if (handler != null)
{
if (this.context != null)
{
this.context.Post(delegate { handler(this, e); }, null);
}
else
{
handler(this, e);
}
}
}
private void ProcessOnExited(object sender, EventArgs eventArgs)
{
this.OnProcessExited();
}
private async void ReadOutputAsync()
{
var standart = new StringBuilder();
var buff = new char[1024];
int length;
while (this.process.HasExited == false)
{
standart.Clear();
length = await this.process.StandardOutput.ReadAsync(buff, 0, buff.Length);
standart.Append(buff.SubArray(0, length));
this.OnStandartTextReceived(standart.ToString());
Thread.Sleep(1);
}
this.Running = false;
}
private async void ReadOutputErrorAsync()
{
var sb = new StringBuilder();
do
{
sb.Clear();
var buff = new char[1024];
int length = await this.process.StandardError.ReadAsync(buff, 0, buff.Length);
sb.Append(buff.SubArray(0, length));
this.OnErrorTextReceived(sb.ToString());
Thread.Sleep(1);
}
while (this.process.HasExited == false);
}
private async void WriteInputTask()
{
while (this.process.HasExited == false)
{
Thread.Sleep(1);
if (this.pendingWriteData != null)
{
await this.process.StandardInput.WriteLineAsync(this.pendingWriteData);
await this.process.StandardInput.FlushAsync();
lock (this.theLock)
{
this.pendingWriteData = null;
}
}
}
}
}
然后,在实际运行该过程并在我的主应用程序中发送CTRL-C:
DateTime maxStartDateTime = //... some date time;
DateTime maxEndDateTime = //... some later date time
var duration = maxEndDateTime.Subtract(maxStartDateTime);
ConsoleAppManager appManager = new ConsoleAppManager("myapp.exe");
string[] args = new string[] { "args here" };
appManager.ExecuteAsync(args);
await Task.Delay(Convert.ToInt32(duration.TotalSeconds * 1000) + 20000);
if (appManager.Running)
{
// If stilll running, send CTRL-C
appManager.Write("\x3");
}