如何使用C#中的STARTUPINFOEX调用CreateProcess()并重新生成子项

我需要创建一个新进程,但是它是另一个进程的“子”而不是当前进程,例如重新父进程。

以下几乎让我有.NET:如何使用C#和.NET中的 STARTUPINFOEX调用CreateProcessAsUser() :如何PInvoke UpdateProcThreadAttribute和http://winprogger.com/launching-a-non-child-process/

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

ProcessCreator.CreateProcess(0)启动记事本作为当前进程的子进程,这是默认行为。 到现在为止还挺好。

如果传入的值不为0,则代码会尝试将Notepad作为进程ID与输入值匹配的进程的子进程启动(我假设此进程现在存在)。

不幸的是,该部分不起作用并抛出以下exception:

检测到FatalExecutionEngineError消息:运行时遇到致命错误。 错误的地址位于0x69a2c7ad,位于线程0x1de0上。 错误代码是0xc0000005。 此错误可能是CLR中的错误,也可能是用户代码的不安全或不可validation部分中的错误。 此错误的常见来源包括COM-interop或PInvoke的用户封送错误,这可能会破坏堆栈。

任何指针都非常赞赏。

您的代码有两个问题。 首先,必须将InitializeProcThreadAttributeListUpdateProcThreadAttribute函数的lpAttributeList参数键入为IntPtr而不使用out修饰符。 其次, UpdateProcThreadAttribute函数的lpValue参数必须是指向属性值的指针 (在您的情况下为parentHandle ),而不是值本身。 以下是固定代码。

 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( 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( IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList); [DllImport("kernel32.dll", SetLastError = true)] static extern bool CloseHandle(IntPtr hObject); 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.cb = Marshal.SizeOf(sInfoEx); IntPtr lpValue = IntPtr.Zero; try { if (parentProcessId > 0) { var lpSize = IntPtr.Zero; var success = InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize); if (success || lpSize == IntPtr.Zero) { return false; } sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize); success = InitializeProcThreadAttributeList(sInfoEx.lpAttributeList, 1, 0, ref lpSize); if (!success) { return false; } var parentHandle = Process.GetProcessById(parentProcessId).Handle; // This value should persist until the attribute list is destroyed using the DeleteProcThreadAttributeList function lpValue = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteIntPtr(lpValue, parentHandle); success = UpdateProcThreadAttribute( sInfoEx.lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, lpValue, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero); if (!success) { return false; } } 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); } finally { // Free the attribute list if (sInfoEx.lpAttributeList != IntPtr.Zero) { DeleteProcThreadAttributeList(sInfoEx.lpAttributeList); Marshal.FreeHGlobal(sInfoEx.lpAttributeList); } Marshal.FreeHGlobal(lpValue); // Close process and thread handles if (pInfo.hProcess != IntPtr.Zero) { CloseHandle(pInfo.hProcess); } if (pInfo.hThread != IntPtr.Zero) { CloseHandle(pInfo.hThread); } } } [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; } }