简体   繁体   English

"创建一个不是创建进程子进程的新进程"

[英]Creating a new process that's not a child of the creating process

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.我正在开发一个应用程序,其中进程 A 的多个实例依赖于进程 B 的单个实例。想法是进程 A 的一个实例启动进程 B,以便 A 的所有实例都可以用它。 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. A 的实例托管在第 3 方进程中,并且可以在不可预测的时间点被拆除(通过杀死进程树)。 It is therefore vital that process B is not a child of any instance of process A.因此,进程 B 不是进程 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).我曾尝试使用 PInvoke 调用 CreateProcess,在创建标志中指定 DetachedProcess (0x08),但这不起作用(请参阅下面的代码)。

[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);
}

You can try to use the ManagementClass to launch a process and pass some CreateFlags , more specifically, the DETACHED_PROCESS flag. 您可以尝试使用ManagementClass启动进程并传递一些CreateFlags ,更具体地说,传递DETACHED_PROCESS标志。 (You'll need to reference System.Management .) (您需要引用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. 至少在我的机器上,记事本不被视为我的控制台测试应用程序的子进程。

You can specify a different parent by using a process attribute.您可以使用进程属性指定不同的父级。 Here is a function that does just that.这是一个可以做到这一点的函数。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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