Como chamar CreateProcess () com STARTUPINFOEX de c # e re-parent a criança

Eu preciso criar um novo processo, mas para que seja um "filho" de outro processo, não o processo atual, por exemplo, re-parentear o novo processo.

O seguinte me pegou quase lá.NET: Como chamar CreateProcessAsUser () com STARTUPINFOEX de c # e.NET: Como PInvoke UpdateProcThreadAttribute ehttp://winprogger.com/launching-a-non-child-process/

<code>using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

public class ProcessCreator
{
    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CreateProcess(
        string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
        ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
        IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo,
        out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UpdateProcThreadAttribute(
        out IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue,
        IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool InitializeProcThreadAttributeList(
        out IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);

    public static bool CreateProcess(int parentProcessId)
    {
        const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
        const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;

        var pInfo = new PROCESS_INFORMATION();
        var sInfoEx = new STARTUPINFOEX();
        sInfoEx.StartupInfo = new STARTUPINFO();

        if (parentProcessId > 0)
        {
            var lpSize = IntPtr.Zero;
            IntPtr dummyPtr;
            var success = InitializeProcThreadAttributeList(out dummyPtr, 1, 0, ref lpSize);
            if (success || lpSize == IntPtr.Zero)
            {
                return false;
            }

            sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize);
            if (sInfoEx.lpAttributeList == IntPtr.Zero)
            {
                return false;
            }

            success = InitializeProcThreadAttributeList(out sInfoEx.lpAttributeList, 1, 0, ref lpSize);
            if (!success)
            {
                return false;
            }

            var parentHandle = Process.GetProcessById(parentProcessId).Handle;
            success = UpdateProcThreadAttribute(
                out sInfoEx.lpAttributeList,
                0,
                (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
                parentHandle,
                (IntPtr)IntPtr.Size,
                IntPtr.Zero,
                IntPtr.Zero);
            if (!success)
            {
                return false;
            }

            sInfoEx.StartupInfo.cb = Marshal.SizeOf(sInfoEx);
        }


        var pSec = new SECURITY_ATTRIBUTES();
        var tSec = new SECURITY_ATTRIBUTES();
        pSec.nLength = Marshal.SizeOf(pSec);
        tSec.nLength = Marshal.SizeOf(tSec);
        var lpApplicationName = Path.Combine(Environment.SystemDirectory, "notepad.exe");
        return CreateProcess(lpApplicationName, null, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFOEX
    {
        public STARTUPINFO StartupInfo;
        public IntPtr lpAttributeList;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }
}
</code>

ProcessCreator.CreateProcess (0) inicia o Bloco de Notas como um filho do processo atual, que é o comportamento padrão. Por enquanto, tudo bem.

Se o valor transmitido for diferente de 0, o código tentará iniciar o Bloco de Notas como um filho do processo cujo ID de processo corresponde ao valor de entrada (suponho que o processo exista agora).

Infelizmente essa parte não funciona e lança a seguinte exceção:

FatalExecutionEngineError foi detectado Mensagem: O tempo de execução encontrou um erro fatal. O endereço do erro estava em 0x69a2c7ad, no thread 0x1de0. O código de erro é 0xc0000005. Esse erro pode ser um bug no CLR ou nas partes inseguras ou não verificáveis ​​do código do usuário. Fontes comuns desse bug incluem erros de empacotamento de usuário para COM-interop ou PInvoke, que podem corromper a pilha.

Quaisquer ponteiros muito apreciados.

questionAnswers(1)

yourAnswerToTheQuestion