Creating a new process that's not a child of the creating process
Asked Answered
T

2

3

I am developing an application in which a number of instances of a process, A, depend on a single instance of a process, B. The idea is that one of the instances of process A starts process B so that all the instances of A can use it. The instances of A are hosted in a 3rd party process and can be torn down (by killing the process tree) at unpredictable points in time. It is therefore vital that process B is not a child of any instance of process A.

I have tried to do this using PInvoke to call CreateProcess, specifying DetachedProcess (0x08) in the creation flags, but this did not work (please see code below).

[DllImport("kernel32.dll")]
private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);


public Process LaunchProcess(Path executablePath, string args)
{
    StartupInfo sInfo = new StartupInfo();

    const uint creationFlags = (uint)(CreationFlags.CreateNoWindow | CreationFlags.DetachedProcess);

    ProcessInformation pInfo;
    bool success = CreateProcess(executablePath.ToString(), args, IntPtr.Zero, IntPtr.Zero, false, creationFlags, IntPtr.Zero, executablePath.GetFolderPath().ToString(), ref sInfo, out pInfo);

    if (!success)
    {
        throw new Win32Exception();
    }

    return Process.GetProcessById(pInfo.dwProcessId);
}

I have also read the article at How to create a process that is not a child of it's creating process?, which suggested using an interim process to start the new process, but I am not keen on this approach as it would complicate the synchronisation around ensuring that only a single instance of process B is started.

Does anyone know of a better way of achieving this?

Tamica answered 22/8, 2012 at 7:56 Comment(1)
Similar question with different solutions: https://mcmap.net/q/346446/-start-new-process-without-being-a-child-of-the-spawning-process/850848Syndesis
I
15

You can try to use the ManagementClass to launch a process and pass some CreateFlags, more specifically, the DETACHED_PROCESS flag. (You'll need to reference System.Management.)

private static void Main()
{
    using (var managementClass = new ManagementClass("Win32_Process"))
    {
        var processInfo = new ManagementClass("Win32_ProcessStartup");
        processInfo.Properties["CreateFlags"].Value = 0x00000008;

        var inParameters = managementClass.GetMethodParameters("Create");
        inParameters["CommandLine"] = "notepad.exe";
        inParameters["ProcessStartupInformation"] = processInfo;

        var result = managementClass.InvokeMethod("Create", inParameters, null);
        if ((result != null) && ((uint)result.Properties["ReturnValue"].Value != 0))
        {
            Console.WriteLine("Process ID: {0}", result.Properties["ProcessId"].Value);
        }
    }

    Console.ReadKey();
}

At least on my machine notepad is not considered a child process of my console test application.

Imogen answered 22/8, 2012 at 8:15 Comment(4)
Hi Jensen, Thanks for your answer. I had considered using WMI, but was hoping that someone would know of a simpler way using CreateProcess or similar. Using ManagementClass as you suggest actually defers creation of the new process to WMI. The result is that the new process is a child of wmiprvse.exe, rather than the creating process. The DETACHED_PROCESS flag makes no difference to this outcome. Its use, as with the equivalent flag in PInvoke / CreateProcess, actually causes the new process to be initialised without a console; it does not control the parent status of the new process.Tamica
I would like to add though that your suggestion would undoubtedly fix my problem as, by breaking the parent child relationship between the instances of process A and process B, killing the process tree for an instance of process A would not kill process B.Tamica
This is exactly what I needed! Saved me a lot of headache.Watchful
This solution solves the parent-child relationship problem that allows the user to end process tree from the task manager in order to end all child processes. This way, there is no way to end the child process from the parent process and vice versa (obviously)Watchful
N
1

You can specify a different parent by using a process attribute. Here is a function that does just that. Although it's written in C++ it shows the idea how it works.

bool CreateProcessWithParent(DWORD parentId, PWSTR commandline) {
    auto hProcess = ::OpenProcess(PROCESS_CREATE_PROCESS, FALSE, parentId);
    if (!hProcess)
        return false;
 
    SIZE_T size;
    //
    // call InitializeProcThreadAttributeList twice
    // first, get required size
    //
    ::InitializeProcThreadAttributeList(nullptr, 1, 0, &size);
 
    //
    // now allocate a buffer with the required size and call again
    //
    auto buffer = std::make_unique<BYTE[]>(size);
    auto attributes = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(buffer.get());
    ::InitializeProcThreadAttributeList(attributes, 1, 0, &size);
 
    //
    // add the parent attribute
    //
    ::UpdateProcThreadAttribute(attributes, 0, 
        PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, 
        &hProcess, sizeof(hProcess), nullptr, nullptr);
 
    STARTUPINFOEX si = { sizeof(si) };
    //
    // set the attribute list
    //
    si.lpAttributeList = attributes;
    PROCESS_INFORMATION pi;
 
    //
    // create the process
    //
    BOOL created = ::CreateProcess(nullptr, commandline, nullptr, nullptr, 
        FALSE, EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, 
        (STARTUPINFO*)&si, &pi);
 
    //
    // cleanup
    //
    ::CloseHandle(hProcess);
    ::DeleteProcThreadAttributeList(attributes);
 
    return created;
}

Source code taken from https://scorpiosoftware.net/2021/01/10/parent-process-vs-creator-process/

Natator answered 3/2, 2022 at 7:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.