[英]Process.Start() and the Process Tree
我如何使用Process.Start(),但启动的进程与启动进程不在同一个进程树中?
考虑此示例控制台应用程序
using System;
using System.Diagnostics;
using System.Threading;
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("Starting ie...");
Process.Start("c:\\Program Files\\Internet Explorer\\iexplore.exe", "http://www.google.com");
Console.WriteLine("Waiting for 15 seconds");
Thread.Sleep(15000);
Console.WriteLine("Exiting...");
}
}
当此程序正常退出时,Internet Explorer将继续运行。 但是,如果在15秒睡眠期间您转到任务管理器并选择此程序并选择“结束进程树”,Internet Explorer也将关闭。
(这与我今天早些时候的问题直接相关,到目前为止,还没有回复。在Windows XP中,当屏幕保护程序结束时,它似乎结束了进程树,而在Vista中,只是屏幕保护程序进程结束。)
Eric是正确的:Windows不公开任何更改进程父级的方法。 但是,如果父母去世,则没有回到祖父母的链接,因此您可以通过启动孩子的中间过程来实现目标,然后死亡。
所以:Proc A启动proc B,然后proc B启动proc C并立即死亡。 当proc B死掉时,proc C将成为进程树上的根节点 - proc B将在proc B死后不在proc A的树中。
在调用Process.Start()之前,尝试将Process.StartInfo.UseShellExecute设置为False(默认情况下为True)。 这样,CreateProcess()在内部使用而不是ShellExecute()。
我不相信Windows公开(通过.NET或其他方式)任何更改进程父级的方法。
作为替代方案,您可以在系统启动时运行单独的进程(例如,通过“SOFTWARE / Microsoft / Windows / CurrentVersion / Run”注册表项),并让触发应用程序(您的屏幕保护程序)使用进程间通信(SendMessage)或者说)告诉单独的进程启动浏览器。 然后,单独的进程将成为父进程,并且当屏幕保护程序的进程树被终止时,浏览器不会被杀死。
这是一些示例代码。 请注意,这不会进行任何错误检查,我没有在实际屏幕保护程序的上下文中测试它,但它应该让您了解所涉及的内容:
在屏幕保护程序类中:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam);
private uint message;
在屏幕保护程序的初始化代码中:
message = RegisterWindowMessage("LaunchBrowser");
在屏幕保护程序的浏览器启动代码中:
SendMessage(FindWindow(null, "BrowserLauncher"), message, UIntPtr.Zero, IntPtr.Zero);
在单独的进程的表单类中:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
private uint message;
在单独的进程的Form_Load代码中:
message = RegisterWindowMessage("LaunchBrowser");
Text = "BrowserLauncher";
并覆盖单独进程的窗体的WndProc:
protected override void WndProc(ref Message m)
{
if (m.Msg == message)
{
Process.Start("iexplore.exe", "http://www.google.com");
}
base.WndProc(ref m);
}
(当然,您需要隐藏单独进程的表单。)
据我所知,Process.Start()不支持你要求的东西。 您必须使用PInvoke直接调用Win32 API CreateProcess()函数,以便您可以在其dwCreationFlags参数中指定DETACHED_PROCESS标志。
您必须分离子进程。 不知道如何在c#中使用,但考虑下面的C ++代码,您可以使用/ P:invoke在.net中实现相同的代码。
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Allow the system to destroy the process & thread kernel
// objects as soon as the child process terminates.
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.