private void StartProcess() { bool retValue; // Create startup info for new console process. STARTUPINFO startupInfo = new STARTUPINFO(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.dwFlags = StartFlags.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = _consoleVisible ? WindowShowStyle.Show : WindowShowStyle.Hide; startupInfo.lpTitle = this.ConsoleTitle ?? "Console"; SECURITY_ATTRIBUTES procAttrs = new SECURITY_ATTRIBUTES(); SECURITY_ATTRIBUTES threadAttrs = new SECURITY_ATTRIBUTES(); procAttrs.nLength = Marshal.SizeOf(procAttrs); threadAttrs.nLength = Marshal.SizeOf(threadAttrs); // Set environment variables for new process. IntPtr pEnvironment = IntPtr.Zero; // Start new console process. retValue = WinApi.CreateProcess(null, this.CommandLine, ref procAttrs, ref threadAttrs, false, CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_SUSPENDED, pEnvironment, null, ref startupInfo, out _procInfo); if (!retValue) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to create new console process."); } _proc = Process.GetProcessById(_procInfo.dwProcessId); // Create objects in shared memory. CreateSharedObjects(_procInfo.dwProcessId); // Write startup parameters to shared memory. unsafe { ConsoleParams *consoleParams = (ConsoleParams *)_consoleParams.Get(); consoleParams->ConsoleMainThreadId = _procInfo.dwThreadId; consoleParams->ParentProcessId = Process.GetCurrentProcess().Id; consoleParams->NotificationTimeout = 10; consoleParams->RefreshInterval = 100; consoleParams->Rows = this.ConsoleInitialWindowHeight; consoleParams->Columns = this.ConsoleInitialWindowWidth; consoleParams->BufferRows = this.ConsoleInitialBufferHeight; consoleParams->BufferColumns = this.ConsoleInitialBufferWidth; } }
private void Dispose(bool disposing) { lock (_disposeLock) { if (!_isDisposed) { if (disposing) { // Dispose managed resources. // Dispose wait handles. if (_procSafeWaitHandle != null) { _procSafeWaitHandle.Dispose(); } // Abort monitor thread. if (_monitorThread != null) { _monitorThread.Abort(); } if (_consoleParams.IsAvailable) { // Close console window. unsafe { ConsoleParams *consoleParams = (ConsoleParams *)_consoleParams.Get(); if (consoleParams->ConsoleWindowHandle != IntPtr.Zero) { WinApi.SendMessage(consoleParams->ConsoleWindowHandle, WinApi.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); } } } // Dispose shared memory objects. if (_consoleParams != null) { _consoleParams.Dispose(); } if (_consoleScreenInfo != null) { _consoleScreenInfo.Dispose(); } if (_consoleCursorInfo != null) { _consoleCursorInfo.Dispose(); } if (_consoleBufferInfo != null) { _consoleBufferInfo.Dispose(); } if (_consoleBuffer != null) { _consoleBuffer.Dispose(); } if (_consoleCopyInfo != null) { _consoleCopyInfo.Dispose(); } if (_consolePasteInfo != null) { _consolePasteInfo.Dispose(); } if (_consoleMouseEvent != null) { _consoleMouseEvent.Dispose(); } if (_consoleNewSizeInfo != null) { _consoleNewSizeInfo.Dispose(); } if (_consoleNewScrollPos != null) { _consoleNewScrollPos.Dispose(); } //// Kill console process. //if (_process != null) //{ // _process.Kill(); // _process.Dispose(); //} } // Dispose unmanaged resources. } _isDisposed = true; } }
private void MonitorThread() { ProcessWaitHandle procWaitHandle = null; WaitHandle[] waitHandles; try { unsafe { // Get pointers to shared memory objects. ConsoleParams *consoleParams = (ConsoleParams *)_consoleParams.Get(); CONSOLE_SCREEN_BUFFER_INFO *consoleScreenInfo = (CONSOLE_SCREEN_BUFFER_INFO *) _consoleScreenInfo.Get(); ConsoleBufferInfo *consoleBufferInfo = (ConsoleBufferInfo *)_consoleBufferInfo.Get(); // Keep waiting for new events until process has exitted or thread is aborted. procWaitHandle = new ProcessWaitHandle(_procSafeWaitHandle); waitHandles = new WaitHandle[] { procWaitHandle, _consoleBufferInfo.RequestEvent }; // Loop until console has exitted. while (WaitHandle.WaitAny(waitHandles) > 0) { // Get current window and buffer size. int columns = consoleScreenInfo->srWindow.Right - consoleScreenInfo->srWindow.Left + 1; int rows = consoleScreenInfo->srWindow.Bottom - consoleScreenInfo->srWindow.Top + 1; int bufferColumns = consoleScreenInfo->dwSize.X; int bufferRows = consoleScreenInfo->dwSize.Y; // Check if window size has changed. if (consoleParams->Columns != columns || consoleParams->Rows != rows) { consoleParams->Columns = columns; consoleParams->Rows = rows; // Raise event, window has been resized. if (ConsoleWindowResized != null) { ConsoleWindowResized(this, new EventArgs()); } } // Check if buffer size has changed. if ((consoleParams->BufferColumns != 0 && consoleParams->BufferColumns != bufferColumns) || (consoleParams->BufferRows != 0 && consoleParams->BufferRows != bufferRows)) { consoleParams->BufferColumns = bufferColumns; consoleParams->BufferRows = bufferRows; // Raise event, buffer has been resized. if (ConsoleBufferResized != null) { ConsoleBufferResized(this, new EventArgs()); } } if (consoleBufferInfo->NewDataFound || consoleBufferInfo->CursorPositionChanged) { // Raise event, console has sent new data. if (ConsoleNewData != null) { ConsoleNewData(this, new EventArgs()); } // Check if new data was found. if (consoleBufferInfo->NewDataFound) { // Raise event, buffer data has changed. if (ConsoleBufferChanged != null) { ConsoleBufferChanged(this, new EventArgs()); } } // Check if cursor posistion has changed. if (consoleBufferInfo->CursorPositionChanged) { // Raise event, cursor position has changed. if (ConsoleCursorPositionChanged != null) { ConsoleCursorPositionChanged(this, new EventArgs()); } } } } } } catch (ThreadAbortException) { } finally { if (procWaitHandle != null) { procWaitHandle.Close(); } // Raise event. if (ConsoleClosed != null) { ConsoleClosed(this, new EventArgs()); } } }
public void Initialize() { int retValue; // Start new console process. StartProcess(); // Inject DLL into console process. InjectDll(this.InjectionDllFileName); // Resume main thread of console process. WinApi.ResumeThread(_procInfo.hThread); WinApi.CloseHandle(_procInfo.hThread); // Wait for DLL to set console handle. retValue = WinApi.WaitForSingleObject(_consoleParams.RequestEvent.SafeWaitHandle .DangerousGetHandle(), 1000); if (retValue == WinApi.WAIT_FAILED) { throw new Win32Exception(); } if (retValue == WinApi.WAIT_TIMEOUT) { throw new TimeoutException(); } // Create wait handle for console process. _procSafeWaitHandle = new SafeWaitHandle(_procInfo.hProcess, false); // Set language of console window. unsafe { ConsoleParams *consoleParams = (ConsoleParams *)_consoleParams.Get(); if (!WinApi.PostMessage(consoleParams->ConsoleWindowHandle, WinApi.WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, new IntPtr(CultureInfo.CurrentCulture.KeyboardLayoutId))) { throw new Win32Exception(); } } // Start thread to monitor console. _monitorThread = new Thread(new ThreadStart(MonitorThread)); _monitorThread.Name = "Console Monitor"; _monitorThread.Start(); // Resume monitor thread. unsafe { ConsoleParams *consoleParams = (ConsoleParams *)_consoleParams.Get(); IntPtr hHookThread = WinApi.OpenThread(ThreadAccess.ALL_ACCESS, false, consoleParams->HookThreadId); if (WinApi.ResumeThread(hHookThread) == -1) { throw new Win32Exception(); } WinApi.CloseHandle(hHookThread); } // Raise event. if (ConsoleOpened != null) { ConsoleOpened(this, new EventArgs()); } }