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

Roy*_*Roy 1 c# windows createprocess

我正在开发一个应用程序,其中进程 A 的多个实例依赖于进程的单个实例 B。这个想法是进程 A 的一个实例启动进程 B,以便 A 的所有实例都可以用它。A 的实例托管在第 3 方进程中,并且可以在不可预测的时间点被拆除(通过终止进程树)。因此,进程 B 不是进程 A 的任何实例的子进程至关重要。

我尝试使用 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);
}
Run Code Online (Sandbox Code Playgroud)

我还阅读了如何创建一个不是其创建过程的子进程的文章?,它建议使用临时进程来启动新进程,但我并不热衷于这种方法,因为它会使围绕确保仅启动进程 B 的单个实例的同步复杂化。

有谁知道实现这一目标的更好方法?

Jen*_*sen 8

您可以尝试使用ManagementClass来启动进程并传递一些CreateFlags,更具体地说,是DETACHED_PROCESS标志。(你需要参考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();
}
Run Code Online (Sandbox Code Playgroud)

至少在我的机器上,记事本不被视为我的控制台测试应用程序的子进程。

  • 嗨,詹森,感谢您的回答。我曾考虑过使用 WMI,但希望有人知道使用 CreateProcess 或类似方法的更简单方法。按照您的建议使用 ManagementClass 实际上会将新进程的创建推迟到 WMI。结果是新进程是 wmiprvse.exe 的子进程,而不是创建进程。DETACHED_PROCESS 标志对此结果没有影响。它的使用,与 PInvoke / CreateProcess 中的等效标志一样,实际上会导致新进程在没有控制台的情况下初始化;它不控制新进程的父状态。 (2认同)