パイプリダイレクト
id:Ozyさんに触発されてちょっと実験してみた。
CreatePipe,DuplicateHandle,CreateProcessをP/Invokeで呼び出して
StreamReaderでStdOutputを読み出すというもの。
以下ソースコード。
const int STARTF_USESHOWWINDOW = 0x00000001; const int STARTF_USESIZE = 0x00000002; const int STARTF_USEPOSITION = 0x00000004; const int STARTF_USECOUNTCHARS = 0x00000008; const int STARTF_USEFILLATTRIBUTE = 0x00000010; const int STARTF_RUNFULLSCREEN = 0x00000020; const int STARTF_FORCEONFEEDBACK = 0x00000040; const int STARTF_FORCEOFFFEEDBACK = 0x00000080; const int STARTF_USESTDHANDLES = 0x00000100; [StructLayout(LayoutKind.Sequential)] internal struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public UInt32 dwProcessId; public UInt32 dwThreadId; } const UInt32 INFINITE = 0xFFFFFFFF; [StructLayout(LayoutKind.Sequential)] internal struct PPROCESS_MEMORY_COUNTERS { public Int32 cb; public UInt32 PageFaultCount; public int PeakWorkingSetSize; public int WorkingSetSize; public int QuotaPeakPagedPoolUsage; public int QuotaPagedPoolUsage; public int QuotaPeakNonPagedPoolUsage; public int QuotaNonPagedPoolUsage; public int PagefileUsage; public int PeakPagefileUsage; } [StructLayout(LayoutKind.Sequential)] internal struct SECURITY_ATTRIBUTES { public int nLength; public IntPtr lpSecurityDescriptor; public bool bInheritHandle; } [StructLayout(LayoutKind.Sequential)] internal struct STARTUPINFO { public int cb; public IntPtr lpReserved; public IntPtr lpDesktop; public IntPtr lpTitle; public int dwX; public int dwY; public int dwXSize; public int dwYSize; public int dwXCountChars; public int dwYCountChars; public int dwFillAttribute; public int dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } const int DUPLICATE_CLOSE_SOURCE = 0x00000001; const int DUPLICATE_SAME_ACCESS = 0x00000002; const int CREATE_NO_WINDOW = 0x08000000; const int CREATE_NEW_CONSOLE = 0x00000010; const short SW_HIDE = 0; [DllImport("kernel32.dll", EntryPoint="CreateProcess", CallingConvention=CallingConvention.Winapi, CharSet=CharSet.Auto, SetLastError=true)] static extern bool CreateProcess(string appName, StringBuilder cmdLine, ref SECURITY_ATTRIBUTES processAttr, ref SECURITY_ATTRIBUTES threadAttr, bool inheritHandles, int creationFlag, IntPtr environment, string curDir, ref STARTUPINFO startupInfo, ref PROCESS_INFORMATION processInfo); [DllImport("kernel32.dll", EntryPoint = "WaitForSingleObject", CallingConvention = CallingConvention.Winapi, SetLastError = true)] static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 timeOut); [DllImport("kernel32.dll", EntryPoint = "CloseHandle", CallingConvention = CallingConvention.Winapi, SetLastError = true)] static extern bool CloseHandle(IntPtr hHandle); [DllImport("kernel32.dll", EntryPoint = "CreatePipe", CallingConvention = CallingConvention.Winapi, SetLastError = true)] static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES secAttr, int nSize); [DllImport("kernel32.dll", EntryPoint = "DuplicateHandle", CallingConvention = CallingConvention.Winapi, SetLastError = true)] static extern bool DuplicateHandle(IntPtr hSrcProcess, IntPtr hSrcHandle, IntPtr hDstProcess, out IntPtr hDstHandle, UInt32 desiredAccess, bool inheritHandle, UInt32 options); [DllImport("kernel32.dll", EntryPoint = "GetCurrentProcess", CallingConvention = CallingConvention.Winapi, SetLastError = true)] static extern IntPtr GetCurrentProcess(); [DllImport("psapi.dll", EntryPoint="GetProcessMemoryInfo", CallingConvention=CallingConvention.Winapi, SetLastError=true)] static extern bool GetProcessMemoryInfo( IntPtr hProcess, ref PPROCESS_MEMORY_COUNTERS processMemoryCounters, Int32 memInfoSize); private void CreatePipeWithSecurityAttributes(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES pipeAttributes, int nSize) { if (!CreatePipe(out hReadPipe, out hWritePipe, ref pipeAttributes, nSize)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } private void CreatePipe(out IntPtr parentHandle, out IntPtr childHandle, bool parentInputs) { SECURITY_ATTRIBUTES security_attributes1 = new SECURITY_ATTRIBUTES(); security_attributes1.nLength = 12; security_attributes1.bInheritHandle = true; IntPtr handle1 = IntPtr.Zero; try { if (parentInputs) { CreatePipeWithSecurityAttributes(out childHandle, out handle1, ref security_attributes1, 0); } else { CreatePipeWithSecurityAttributes(out handle1, out childHandle, ref security_attributes1, 0); } if (!DuplicateHandle(GetCurrentProcess(), handle1, GetCurrentProcess(), out parentHandle, 0, false, DUPLICATE_SAME_ACCESS)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { if (handle1 != IntPtr.Zero) { CloseHandle(handle1); } } } private void CreateProcess(string fileName) { SECURITY_ATTRIBUTES processAttr = new SECURITY_ATTRIBUTES(); SECURITY_ATTRIBUTES threadAttr = new SECURITY_ATTRIBUTES(); processAttr.nLength = Marshal.SizeOf(processAttr); threadAttr.nLength = Marshal.SizeOf(threadAttr); processAttr.bInheritHandle = true; threadAttr.bInheritHandle = true; STARTUPINFO si = new STARTUPINFO(); si.cb = Marshal.SizeOf(si); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); PPROCESS_MEMORY_COUNTERS pmc = new PPROCESS_MEMORY_COUNTERS(); pmc.cb = Marshal.SizeOf(pmc); IntPtr hStdOutReadPipe; IntPtr hStdOutWritePipe; IntPtr hStdInReadPipe; IntPtr hStdInWritePipe; IntPtr hStdErrReadPipe; IntPtr hStdErrWritePipe; SECURITY_ATTRIBUTES pipeAttr = new SECURITY_ATTRIBUTES(); pipeAttr.nLength = Marshal.SizeOf(pipeAttr); pipeAttr.bInheritHandle = true; CreatePipe(out hStdInWritePipe, out hStdInReadPipe, true); CreatePipe(out hStdOutReadPipe, out hStdOutWritePipe, false); CreatePipe(out hStdErrReadPipe, out hStdErrWritePipe, false); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdInput = hStdInReadPipe; si.hStdOutput = hStdOutWritePipe; si.hStdError = hStdErrWritePipe; string outStr = ""; if (!CreateProcess(null, new StringBuilder(fileName), ref processAttr, ref threadAttr, true, CREATE_NO_WINDOW, IntPtr.Zero, null, ref si, ref pi)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (CloseHandle(hStdInReadPipe)) { hStdInReadPipe = IntPtr.Zero; } if (CloseHandle(hStdOutWritePipe)) { hStdOutWritePipe = IntPtr.Zero; } if (CloseHandle(hStdErrWritePipe)) { hStdErrWritePipe = IntPtr.Zero; } using (StreamReader sr = new StreamReader(new FileStream(hStdOutReadPipe, FileAccess.Read, false, 0x1000), Encoding.ASCII, true, 0x1000)) { outStr = sr.ReadToEnd(); } WaitForSingleObject(pi.hProcess, INFINITE); if (CloseHandle(pi.hThread)) { pi.hThread = IntPtr.Zero; } if (!GetProcessMemoryInfo(pi.hProcess, ref pmc, Marshal.SizeOf(pmc))) { throw new Win32Exception(Marshal.GetLastWin32Error()); } outStr += string.Format("\r\n\r\nWorkingSetSize = {0}(byte)\r\n", pmc.WorkingSetSize); if (CloseHandle(hStdInWritePipe)) { hStdInWritePipe = IntPtr.Zero; } if (CloseHandle(hStdOutReadPipe)) { hStdOutReadPipe = IntPtr.Zero; } if (CloseHandle(hStdErrReadPipe)) { hStdErrReadPipe = IntPtr.Zero; } if (CloseHandle(pi.hProcess)) { pi.hProcess = IntPtr.Zero; } }