public CHAR_INFO[] GetConsoleBuffer()
        {
            unsafe
            {
                ConsoleBufferInfo *bufferInfo = (ConsoleBufferInfo *)_consoleBufferInfo.Get();
                CHAR_INFO[]        buffer     = new CHAR_INFO[bufferInfo->BufferSize];

                fixed(CHAR_INFO *dst = buffer)
                {
                    WinApi.CopyMemory(new IntPtr(dst), new IntPtr(_consoleBuffer.Get()),
                                      (uint)(buffer.Length * Marshal.SizeOf(typeof(CHAR_INFO))));
                }

                return(buffer);

                //CONSOLE_SCREEN_BUFFER_INFO* consoleScreenInfo = (CONSOLE_SCREEN_BUFFER_INFO*)
                //    _consoleScreenInfo.Get();
                //CHAR_INFO[] buffer = new CHAR_INFO[_consoleBuffer.Size];

                //fixed (CHAR_INFO* dst = buffer)
                //{
                //    WinApi.CopyMemory(new IntPtr(dst), new IntPtr(_consoleBuffer.Get()),
                //        (uint)(buffer.Length * Marshal.SizeOf(typeof(CHAR_INFO))));
                //}

                //return buffer;
            }
        }
        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());
                }
            }
        }