Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading;
- public static class Kernel32
- {
- public const int HANDLE_FLAG_INHERIT = 1;
- public const UInt32 STARTF_USESTDHANDLES = 0x00000100;
- public const UInt32 STARTF_USESHOWWINDOW = 0x00000001;
- public struct SECURITY_ATTRIBUTES
- {
- public int length;
- public IntPtr lpSecurityDescriptor;
- [MarshalAs(UnmanagedType.Bool)]
- public bool bInheritHandle;
- }
- public struct STARTUPINFO
- {
- public uint cb;
- public string lpReserved;
- public string lpDesktop;
- public string lpTitle;
- public uint dwX;
- public uint dwY;
- public uint dwXSize;
- public uint dwYSize;
- public uint dwXCountChars;
- public uint dwYCountChars;
- public uint dwFillAttribute;
- public uint dwFlags;
- public short wShowWindow;
- public short cbReserved2;
- public IntPtr lpReserved2;
- public IntPtr hStdInput;
- public IntPtr hStdOutput;
- public IntPtr hStdError;
- }
- public struct PROCESS_INFORMATION
- {
- public IntPtr hProcess;
- public IntPtr hThread;
- public uint dwProcessId;
- public uint dwThreadId;
- }
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool CreateProcess(string lpApplicationName,
- string lpCommandLine,
- IntPtr lpProcessAttributes,
- IntPtr lpThreadAttributes,
- [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles,
- uint dwCreationFlags,
- IntPtr lpEnvironment,
- string lpCurrentDirectory,
- ref STARTUPINFO lpStartupInfo,
- out PROCESS_INFORMATION lpProcessInformation);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool CloseHandle(IntPtr hObject);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool CreatePipe(out IntPtr hReadPipe,
- out IntPtr hWritePipe,
- ref SECURITY_ATTRIBUTES lpPipeAttributes,
- uint nSize);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern unsafe bool PeekNamedPipe(IntPtr hNamedPipe,
- IntPtr pBuffer,
- int nBufferSize,
- IntPtr lpBytesRead,
- int* lpTotalBytesAvail,
- IntPtr lpBytesLeftThisMessage);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern unsafe bool ReadFile(IntPtr hFile,
- void* pBuffer,
- int nNumberOfBytesToRead,
- int* lpNumberOfBytesRead,
- IntPtr lpOverlapped);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern unsafe bool WriteFile(IntPtr hFile,
- void* pBuffer,
- int nNumberOfBytesToWrite,
- int* lpNumberOfBytesWritten,
- IntPtr lpOverlapped);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SetHandleInformation(IntPtr hObject, int dwMask, uint dwFlags);
- }
- public abstract class ShellProcess
- {
- IntPtr _hStdoutR, _hStdoutW, _hStderrR, _hStderrW, _hStdinR, _hStdinW;
- Kernel32.SECURITY_ATTRIBUTES _sa;
- Kernel32.STARTUPINFO _si;
- Kernel32.PROCESS_INFORMATION _pi;
- string _applicationName;
- protected abstract string Prompt { get; }
- protected abstract string ExitCommand { get; }
- protected abstract Encoding Encoding { get; }
- static unsafe int Write(IntPtr h, byte[] buffer, int index, int count)
- {
- int n = 0;
- fixed (byte* p = buffer) {
- if (!Kernel32.WriteFile(h, p + index, count, &n, IntPtr.Zero))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
- return n;
- }
- static unsafe int Peek(IntPtr h)
- {
- int n = 0;
- if (!Kernel32.PeekNamedPipe(h, IntPtr.Zero, 0, IntPtr.Zero, &n, IntPtr.Zero))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- return n;
- }
- static unsafe int Read(IntPtr h, byte[] buffer, int index, int count)
- {
- int n = 0;
- fixed (byte* p = buffer) {
- if (!Kernel32.ReadFile(h, p + index, count, &n, IntPtr.Zero))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
- return n;
- }
- void SendCommand(string s)
- {
- byte[] bytesToWrite = Encoding.GetBytes(s + "\r\n");
- Write(_hStdinW, bytesToWrite, 0, bytesToWrite.Length);
- }
- Tuple<string, string> ReadToPrompt()
- {
- const int bufferLength = 128;
- byte[] buffer = new byte[bufferLength];
- int bytesReadCount;
- var stdOut = new StringBuilder(4096);
- var stdErr = new StringBuilder();
- while (!stdOut.ToString().EndsWith("\n" + Prompt) && stdOut.ToString() != Prompt) {
- while (Peek(_hStderrR) > 0) {
- bytesReadCount = Read(_hStderrR, buffer, 0, bufferLength);
- stdErr.Append(Encoding.GetString(buffer, 0, bytesReadCount));
- }
- while (Peek(_hStdoutR) > 0) {
- bytesReadCount = Read(_hStdoutR, buffer, 0, bufferLength);
- stdOut.Append(Encoding.GetString(buffer, 0, bytesReadCount));
- }
- Thread.Sleep(20);
- }
- while (Peek(_hStderrR) > 0) {
- bytesReadCount = Read(_hStderrR, buffer, 0, bufferLength);
- stdErr.Append(Encoding.GetString(buffer, 0, bytesReadCount));
- }
- return new Tuple<string, string>(stdOut.ToString(), stdErr.ToString());
- }
- /// <summary>
- /// Read stdout and stderr until prompt is printed.
- /// </summary>
- /// <param name="toSend">What to send without the line-feed and carriage return.</param>
- /// <returns>A 2-string Tuple; the first item is stdout, the second stderr.</returns>
- /// <remarks>This method may never return as it doesn't have a time-out.</remarks>
- public Tuple<string, string> SendAndReceive(string toSend)
- {
- SendCommand(toSend);
- return ReadToPrompt();
- }
- /// <summary>
- /// Start shell.
- /// </summary>
- /// <param name="applicationName"></param>
- /// <param name="workDirectory"></param>
- public void Start(string applicationName, string workDirectory)
- {
- _sa = new Kernel32.SECURITY_ATTRIBUTES {
- bInheritHandle = true,
- lpSecurityDescriptor = IntPtr.Zero,
- length = Marshal.SizeOf(typeof(Kernel32.SECURITY_ATTRIBUTES))
- };
- _sa.lpSecurityDescriptor = IntPtr.Zero;
- if (!Kernel32.CreatePipe(out _hStdoutR, out _hStdoutW, ref _sa, 0))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.CreatePipe(out _hStderrR, out _hStderrW, ref _sa, 0))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.CreatePipe(out _hStdinR, out _hStdinW, ref _sa, 0))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.SetHandleInformation(_hStdoutR, Kernel32.HANDLE_FLAG_INHERIT, 0))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.SetHandleInformation(_hStderrR, Kernel32.HANDLE_FLAG_INHERIT, 0))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.SetHandleInformation(_hStdinW, Kernel32.HANDLE_FLAG_INHERIT, 0))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- _si = new Kernel32.STARTUPINFO {
- wShowWindow = 0,
- dwFlags = Kernel32.STARTF_USESTDHANDLES | Kernel32.STARTF_USESHOWWINDOW,
- hStdOutput = _hStdoutW,
- hStdError = _hStderrW,
- hStdInput = _hStdinR
- };
- _si.cb = (uint)Marshal.SizeOf(_si);
- _pi = new Kernel32.PROCESS_INFORMATION();
- if (!Kernel32.CreateProcess(applicationName, null, IntPtr.Zero, IntPtr.Zero, true, 0, IntPtr.Zero, workDirectory, ref _si, out _pi))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- _applicationName = applicationName;
- ReadToPrompt();
- }
- /// <summary>
- /// Tell shell to exit and free resources.
- /// </summary>
- public void Terminate()
- {
- SendCommand(ExitCommand);
- if (!Kernel32.CloseHandle(_hStderrW))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.CloseHandle(_hStdoutW))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.CloseHandle(_hStdinW))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.CloseHandle(_pi.hProcess))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- if (!Kernel32.CloseHandle(_pi.hThread))
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
- }
Add Comment
Please, Sign In to add comment