using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; namespace ZC; 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,out PROCESS_INFORMATION pInfo) { const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000; const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000; pInfo = new PROCESS_INFORMATION(); var sInfoEx = new STARTUPINFOEX(); var securityAttributes = new SECURITY_ATTRIBUTES(); securityAttributes.nLength = 1; sInfoEx.StartupInfo = new STARTUPINFO(); var input = CreateFile("./inputfile1", DesiredAccess.GENERIC_READ, 0, ref securityAttributes, CreationDisposition.OPEN_EXISTING, 0, IntPtr.Zero); var output = CreateFile("./test.log", DesiredAccess.GENERIC_WRITE, 0, ref securityAttributes, CreationDisposition.CREATE_NEW, 0, IntPtr.Zero); sInfoEx.StartupInfo.hStdInput = input; sInfoEx.StartupInfo.hStdOutput = output; sInfoEx.StartupInfo.hStdError = output; sInfoEx.StartupInfo.wShowWindow = 0; 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)] public 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; } [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr CreateFile(string lpFileName, DesiredAccess dwDesiredAccess, uint dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, CreationDisposition dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); public enum DesiredAccess : uint { GENERIC_WRITE = 30, GENERIC_READ = 31 } public enum CreationDisposition : uint { CREATE_NEW = 1, CREATE_ALWAYS = 2, OPEN_EXISTING = 3, OPEN_ALWAYS = 4, TRUNCATE_EXISTING = 5 } }