繁体   English   中英

Process.Start()和Process Tree

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM