Guest User

Untitled

a guest
Dec 13th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.74 KB | None | 0 0
  1. using System;
  2. using System.ComponentModel;
  3. using System.Diagnostics;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using System.Threading;
  7.  
  8. public static class Kernel32
  9. {
  10. public const int HANDLE_FLAG_INHERIT = 1;
  11. public const UInt32 STARTF_USESTDHANDLES = 0x00000100;
  12. public const UInt32 STARTF_USESHOWWINDOW = 0x00000001;
  13.  
  14. public struct SECURITY_ATTRIBUTES
  15. {
  16. public int length;
  17. public IntPtr lpSecurityDescriptor;
  18. [MarshalAs(UnmanagedType.Bool)]
  19. public bool bInheritHandle;
  20. }
  21.  
  22. public struct STARTUPINFO
  23. {
  24. public uint cb;
  25. public string lpReserved;
  26. public string lpDesktop;
  27. public string lpTitle;
  28. public uint dwX;
  29. public uint dwY;
  30. public uint dwXSize;
  31. public uint dwYSize;
  32. public uint dwXCountChars;
  33. public uint dwYCountChars;
  34. public uint dwFillAttribute;
  35. public uint dwFlags;
  36. public short wShowWindow;
  37. public short cbReserved2;
  38. public IntPtr lpReserved2;
  39. public IntPtr hStdInput;
  40. public IntPtr hStdOutput;
  41. public IntPtr hStdError;
  42. }
  43.  
  44. public struct PROCESS_INFORMATION
  45. {
  46. public IntPtr hProcess;
  47. public IntPtr hThread;
  48. public uint dwProcessId;
  49. public uint dwThreadId;
  50. }
  51.  
  52. [DllImport("kernel32.dll", SetLastError = true)]
  53. [return: MarshalAs(UnmanagedType.Bool)]
  54. public static extern bool CreateProcess(string lpApplicationName,
  55. string lpCommandLine,
  56. IntPtr lpProcessAttributes,
  57. IntPtr lpThreadAttributes,
  58. [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles,
  59. uint dwCreationFlags,
  60. IntPtr lpEnvironment,
  61. string lpCurrentDirectory,
  62. ref STARTUPINFO lpStartupInfo,
  63. out PROCESS_INFORMATION lpProcessInformation);
  64.  
  65. [DllImport("kernel32.dll", SetLastError = true)]
  66. [return: MarshalAs(UnmanagedType.Bool)]
  67. public static extern bool CloseHandle(IntPtr hObject);
  68.  
  69. [DllImport("kernel32.dll", SetLastError = true)]
  70. [return: MarshalAs(UnmanagedType.Bool)]
  71. public static extern bool CreatePipe(out IntPtr hReadPipe,
  72. out IntPtr hWritePipe,
  73. ref SECURITY_ATTRIBUTES lpPipeAttributes,
  74. uint nSize);
  75.  
  76. [DllImport("kernel32.dll", SetLastError = true)]
  77. [return: MarshalAs(UnmanagedType.Bool)]
  78. public static extern unsafe bool PeekNamedPipe(IntPtr hNamedPipe,
  79. IntPtr pBuffer,
  80. int nBufferSize,
  81. IntPtr lpBytesRead,
  82. int* lpTotalBytesAvail,
  83. IntPtr lpBytesLeftThisMessage);
  84.  
  85. [DllImport("kernel32.dll", SetLastError = true)]
  86. [return: MarshalAs(UnmanagedType.Bool)]
  87. public static extern unsafe bool ReadFile(IntPtr hFile,
  88. void* pBuffer,
  89. int nNumberOfBytesToRead,
  90. int* lpNumberOfBytesRead,
  91. IntPtr lpOverlapped);
  92.  
  93. [DllImport("kernel32.dll", SetLastError = true)]
  94. [return: MarshalAs(UnmanagedType.Bool)]
  95. public static extern unsafe bool WriteFile(IntPtr hFile,
  96. void* pBuffer,
  97. int nNumberOfBytesToWrite,
  98. int* lpNumberOfBytesWritten,
  99. IntPtr lpOverlapped);
  100.  
  101. [DllImport("kernel32.dll", SetLastError = true)]
  102. [return: MarshalAs(UnmanagedType.Bool)]
  103. public static extern bool SetHandleInformation(IntPtr hObject, int dwMask, uint dwFlags);
  104. }
  105.  
  106. public abstract class ShellProcess
  107. {
  108. IntPtr _hStdoutR, _hStdoutW, _hStderrR, _hStderrW, _hStdinR, _hStdinW;
  109. Kernel32.SECURITY_ATTRIBUTES _sa;
  110. Kernel32.STARTUPINFO _si;
  111. Kernel32.PROCESS_INFORMATION _pi;
  112. string _applicationName;
  113.  
  114. protected abstract string Prompt { get; }
  115. protected abstract string ExitCommand { get; }
  116. protected abstract Encoding Encoding { get; }
  117.  
  118. static unsafe int Write(IntPtr h, byte[] buffer, int index, int count)
  119. {
  120. int n = 0;
  121. fixed (byte* p = buffer) {
  122. if (!Kernel32.WriteFile(h, p + index, count, &n, IntPtr.Zero))
  123. throw new Win32Exception(Marshal.GetLastWin32Error());
  124. }
  125. return n;
  126. }
  127.  
  128. static unsafe int Peek(IntPtr h)
  129. {
  130. int n = 0;
  131. if (!Kernel32.PeekNamedPipe(h, IntPtr.Zero, 0, IntPtr.Zero, &n, IntPtr.Zero))
  132. throw new Win32Exception(Marshal.GetLastWin32Error());
  133. return n;
  134. }
  135.  
  136. static unsafe int Read(IntPtr h, byte[] buffer, int index, int count)
  137. {
  138. int n = 0;
  139. fixed (byte* p = buffer) {
  140. if (!Kernel32.ReadFile(h, p + index, count, &n, IntPtr.Zero))
  141. throw new Win32Exception(Marshal.GetLastWin32Error());
  142. }
  143. return n;
  144. }
  145.  
  146. void SendCommand(string s)
  147. {
  148. byte[] bytesToWrite = Encoding.GetBytes(s + "\r\n");
  149. Write(_hStdinW, bytesToWrite, 0, bytesToWrite.Length);
  150. }
  151.  
  152. Tuple<string, string> ReadToPrompt()
  153. {
  154. const int bufferLength = 128;
  155. byte[] buffer = new byte[bufferLength];
  156. int bytesReadCount;
  157. var stdOut = new StringBuilder(4096);
  158. var stdErr = new StringBuilder();
  159.  
  160. while (!stdOut.ToString().EndsWith("\n" + Prompt) && stdOut.ToString() != Prompt) {
  161. while (Peek(_hStderrR) > 0) {
  162. bytesReadCount = Read(_hStderrR, buffer, 0, bufferLength);
  163. stdErr.Append(Encoding.GetString(buffer, 0, bytesReadCount));
  164. }
  165. while (Peek(_hStdoutR) > 0) {
  166. bytesReadCount = Read(_hStdoutR, buffer, 0, bufferLength);
  167. stdOut.Append(Encoding.GetString(buffer, 0, bytesReadCount));
  168. }
  169. Thread.Sleep(20);
  170. }
  171. while (Peek(_hStderrR) > 0) {
  172. bytesReadCount = Read(_hStderrR, buffer, 0, bufferLength);
  173. stdErr.Append(Encoding.GetString(buffer, 0, bytesReadCount));
  174. }
  175.  
  176. return new Tuple<string, string>(stdOut.ToString(), stdErr.ToString());
  177. }
  178.  
  179. /// <summary>
  180. /// Read stdout and stderr until prompt is printed.
  181. /// </summary>
  182. /// <param name="toSend">What to send without the line-feed and carriage return.</param>
  183. /// <returns>A 2-string Tuple; the first item is stdout, the second stderr.</returns>
  184. /// <remarks>This method may never return as it doesn't have a time-out.</remarks>
  185. public Tuple<string, string> SendAndReceive(string toSend)
  186. {
  187. SendCommand(toSend);
  188. return ReadToPrompt();
  189. }
  190.  
  191. /// <summary>
  192. /// Start shell.
  193. /// </summary>
  194. /// <param name="applicationName"></param>
  195. /// <param name="workDirectory"></param>
  196. public void Start(string applicationName, string workDirectory)
  197. {
  198. _sa = new Kernel32.SECURITY_ATTRIBUTES {
  199. bInheritHandle = true,
  200. lpSecurityDescriptor = IntPtr.Zero,
  201. length = Marshal.SizeOf(typeof(Kernel32.SECURITY_ATTRIBUTES))
  202. };
  203. _sa.lpSecurityDescriptor = IntPtr.Zero;
  204.  
  205. if (!Kernel32.CreatePipe(out _hStdoutR, out _hStdoutW, ref _sa, 0))
  206. throw new Win32Exception(Marshal.GetLastWin32Error());
  207. if (!Kernel32.CreatePipe(out _hStderrR, out _hStderrW, ref _sa, 0))
  208. throw new Win32Exception(Marshal.GetLastWin32Error());
  209. if (!Kernel32.CreatePipe(out _hStdinR, out _hStdinW, ref _sa, 0))
  210. throw new Win32Exception(Marshal.GetLastWin32Error());
  211. if (!Kernel32.SetHandleInformation(_hStdoutR, Kernel32.HANDLE_FLAG_INHERIT, 0))
  212. throw new Win32Exception(Marshal.GetLastWin32Error());
  213. if (!Kernel32.SetHandleInformation(_hStderrR, Kernel32.HANDLE_FLAG_INHERIT, 0))
  214. throw new Win32Exception(Marshal.GetLastWin32Error());
  215. if (!Kernel32.SetHandleInformation(_hStdinW, Kernel32.HANDLE_FLAG_INHERIT, 0))
  216. throw new Win32Exception(Marshal.GetLastWin32Error());
  217.  
  218. _si = new Kernel32.STARTUPINFO {
  219. wShowWindow = 0,
  220. dwFlags = Kernel32.STARTF_USESTDHANDLES | Kernel32.STARTF_USESHOWWINDOW,
  221. hStdOutput = _hStdoutW,
  222. hStdError = _hStderrW,
  223. hStdInput = _hStdinR
  224. };
  225.  
  226. _si.cb = (uint)Marshal.SizeOf(_si);
  227. _pi = new Kernel32.PROCESS_INFORMATION();
  228.  
  229. if (!Kernel32.CreateProcess(applicationName, null, IntPtr.Zero, IntPtr.Zero, true, 0, IntPtr.Zero, workDirectory, ref _si, out _pi))
  230. throw new Win32Exception(Marshal.GetLastWin32Error());
  231. _applicationName = applicationName;
  232. ReadToPrompt();
  233. }
  234.  
  235. /// <summary>
  236. /// Tell shell to exit and free resources.
  237. /// </summary>
  238. public void Terminate()
  239. {
  240. SendCommand(ExitCommand);
  241. if (!Kernel32.CloseHandle(_hStderrW))
  242. throw new Win32Exception(Marshal.GetLastWin32Error());
  243. if (!Kernel32.CloseHandle(_hStdoutW))
  244. throw new Win32Exception(Marshal.GetLastWin32Error());
  245. if (!Kernel32.CloseHandle(_hStdinW))
  246. throw new Win32Exception(Marshal.GetLastWin32Error());
  247. if (!Kernel32.CloseHandle(_pi.hProcess))
  248. throw new Win32Exception(Marshal.GetLastWin32Error());
  249. if (!Kernel32.CloseHandle(_pi.hThread))
  250. throw new Win32Exception(Marshal.GetLastWin32Error());
  251. }
  252. }
Add Comment
Please, Sign In to add comment