Вопрос по .net, c# – Process.Start () и дерево процессов

8

Как я могу использовать 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 завершается только процесс заставки.)

Вы решили эту проблему? У меня та же проблема...stackoverflow.com/questions/8364671/… robob

Ваш Ответ

5   ответов
2

что Windows предоставляет (через .NET или иным способом) какой-либо способ изменения родителя процесса.

В качестве альтернативы вы могли бы запустить отдельный процесс при запуске системы (например, через раздел реестра «ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ / 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);
}

(Вы, конечно, захотите скрыть форму отдельного процесса.)

0

что делать в 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);
}
15

Windows не предоставляет никакого способа изменения родительского процесса. Однако, если родитель умирает, ссылка на дедушку отсутствует, поэтому вы можете достичь своей цели с помощью промежуточного процесса, который запускает ребенка, а затем умирает.

Итак: Proc A запускает proc B, затем proc B запускает proc C и немедленно умирает. Когда proc B умирает, proc C будет корневым узлом в дереве процессов - proc C НЕ будет в дереве proc A после смерти proc B.

Очень умно ... и похоже, что вы действительно можете использовать cmd.exe в качестве промежуточного процесса: Process.Start (& quot; cmd.exe & quot; / c start iexplore.exe & lt; url & gt; & quot;); Хороший ответ, и намного проще, чем мой! :-)
Это действительно работает; к сожалению, это не решило мою первоначальную проблему ...: - / user127665
ЗачемProcess.GetProcessByName() не может получить "proc C"; больше после того, как он был отделен от B?
1

олчанию это True) перед вызовом Process.Start (). Таким образом, CreateProcess () используется внутри вместо ShellExecute ().

0

Process.Start () не поддерживает то, что вы просите. Вам придется использовать PInvoke для непосредственного вызова функции Win32 API CreateProcess (), чтобы вы могли указать флаг DETACHED_PROCESS в его параметре dwCreationFlags.

DETACHED_PROCESS приводит к тому, что дочерний процесс не присоединяется к окну консоли родительского процесса; это не связано с деревом процессов.

Похожие вопросы