2 using System.Diagnostics;
\r
3 using System.Runtime.InteropServices;
\r
5 namespace NaGet.InteropServices
\r
7 public class CreateProcessCaller : IDisposable
\r
12 [StructLayout(LayoutKind.Sequential)]
\r
13 internal struct SECURITY_ATTRIBUTES
\r
16 public IntPtr lpSecurityDescriptor;
\r
17 public int bInheritHandle;
\r
21 [StructLayout(LayoutKind.Sequential)]
\r
22 internal struct PROCESS_INFORMATION
\r
24 public IntPtr hProcess;
\r
25 public IntPtr hThread;
\r
26 public int dwProcessId;
\r
27 public int dwThreadId;
\r
30 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
\r
41 Int32 dwXCountChars;
\r
42 Int32 dwYCountChars;
\r
43 Int32 dwFillAttribute;
\r
53 [DllImport("kernel32.dll", CharSet= CharSet.Auto, SetLastError=true)]
\r
54 static extern bool CreateProcess(string lpApplicationName,
\r
55 string lpCommandLine,
\r
56 /* ref SECURITY_ATTRIBUTES lpProcessAttributes, */
\r
57 IntPtr lpProcessAttributes,
\r
58 /* ref SECURITY_ATTRIBUTES lpThreadAttributes, */
\r
59 IntPtr lpThreadAttributes,
\r
60 bool bInheritHandles,
\r
61 uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
\r
62 [In] ref STARTUPINFO lpStartupInfo,
\r
63 out PROCESS_INFORMATION lpProcessInformation);
\r
65 [DllImport("kernel32", SetLastError=true, ExactSpelling=true)]
\r
66 static extern UInt32 WaitForSingleObject(IntPtr handle, UInt32 milliseconds);
\r
68 [DllImport("kernel32.dll", SetLastError=true)]
\r
69 [return: MarshalAs(UnmanagedType.Bool)]
\r
70 static extern bool CloseHandle(IntPtr hObject);
\r
72 [DllImport("kernel32.dll", SetLastError = true)]
\r
73 [return: MarshalAs(UnmanagedType.Bool)]
\r
74 static extern bool GetExitCodeProcess(IntPtr hProcess, out int lpExitCode);
\r
79 PROCESS_INFORMATION pi;
\r
81 public CreateProcessCaller(ProcessStartInfo procInfo)
\r
83 if (procInfo.UseShellExecute) {
\r
84 throw new ArgumentException("UseShellExecute must be false");
\r
86 si.cb = Marshal.SizeOf(si);
\r
88 string lpFileName = (string.IsNullOrEmpty(procInfo.FileName))? null : procInfo.FileName;
\r
90 uint dwCreationFlags = 0x0020; // NORMAL_PRIORITY_CLASS
\r
91 if (procInfo.CreateNoWindow) dwCreationFlags |= 0x08000000; // CREATE_NO_WINDOW
\r
92 string lpCurrentDirectory = (System.IO.Directory.Exists(procInfo.WorkingDirectory))? procInfo.WorkingDirectory : null;
\r
94 bool retValue = CreateProcess(lpFileName, procInfo.Arguments,
\r
95 IntPtr.Zero, IntPtr.Zero,
\r
96 false, dwCreationFlags,
\r
97 IntPtr.Zero, lpCurrentDirectory, ref si, out pi);
\r
99 throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
\r
101 CloseHandle(pi.hThread);
\r
104 public uint WaitForExit(uint timeout)
\r
106 return WaitForSingleObject(pi.hProcess, timeout);
\r
109 public uint WaitForExit()
\r
111 // return WaitForExit(INFINITE)
\r
112 return WaitForExit(0xFFFFFFFF);
\r
115 public int ExitCode {
\r
118 if (! GetExitCodeProcess(pi.hProcess, out lpExitCode) ) {
\r
119 throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
\r
125 public void Dispose()
\r
127 CloseHandle(pi.hProcess);
\r