2

プロセス A の多数のインスタンスがプロセス B の 1 つのインスタンスに依存するアプリケーションを開発しています。プロセス A のインスタンスの 1 つがプロセス B を開始し、A のすべてのインスタンスが実行できるようにするという考え方です。これを使って。A のインスタンスはサード パーティのプロセスでホストされており、予測できない時点で (プロセス ツリーを強制終了することによって) 取り壊される可能性があります。したがって、プロセス 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);
}

How to create a process that is not a child of it's creation process? の記事も読みました。、中間プロセスを使用して新しいプロセスを開始することを提案しましたが、プロセス B の単一のインスタンスのみが開始されるようにするための同期が複雑になるため、このアプローチには熱心ではありません。

これを達成するためのより良い方法を知っている人はいますか?

4

2 に答える 2

11

を使用し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();
}

少なくとも私のマシンでは、メモ帳はコンソール テスト アプリケーションの子プロセスとは見なされません。

于 2012-08-22T08:15:19.037 に答える
1

プロセス属性を使用して別の親を指定できます。これがまさにそれを行う関数です。C++ で書かれていますが、それがどのように機能するかを示しています。

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

https://scorpiosoftware.net/2021/01/10/parent-process-vs-creator-process/から取得したソース コード

于 2022-02-03T07:10:12.957 に答える