Example #1
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="parentForm">The connection form that will display the PowerShell console.</param>
 /// <param name="terminal">Terminal control that will display the PowerShell console.</param>
 /// <param name="executeHelper">Method used to execute PowerShell commands within the current session.</param>
 /// <param name="progressBar">Progress bar UI element to update when writing progress records.</param>
 /// <param name="progressLabel">Label UI element to update when writing progress records.</param>
 public PowerShellHost(
     PowerShellConnectionForm parentForm, TerminalControl terminal, StreamConnection connection, Func <string, Collection <PSObject> > executeHelper, ToolStripProgressBar progressBar,
     ToolStripStatusLabel progressLabel)
 {
     _parentForm       = parentForm;
     _powerShellHostUi = new PowerShellHostUi(terminal, connection, executeHelper, progressBar, progressLabel);
 }
Example #2
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="terminal">Terminal control that will display the PowerShell console.</param>
 public PowerShellRawUi(TerminalControl terminal, StreamConnection connection)
 {
     _terminal        = terminal;
     _backgroundColor = ClosestConsoleColor(_terminal.BackColor);
     _foregroundColor = ClosestConsoleColor(_terminal.ForeColor);
     _connection      = connection;
 }
Example #3
0
        /// <summary>
        /// This API Reads a pressed, released, or pressed and released keystroke from the keyboard device, blocking processing until a keystroke is typed that
        /// matches the specified keystroke options.
        /// </summary>
        /// <param name="options">Options, such as IncludeKeyDown, used when reading the keyboard.</param>
        /// <returns>Data for the key that the user pressed.</returns>
        public override KeyInfo ReadKey(ReadKeyOptions options)
        {
            StreamConnection connection = _terminal.TerminalPane.ConnectionTag.Connection as StreamConnection;

            connection.Capture = true;
            _inputSemaphore.Reset();

            // Start up a thread to watch the terminal's input bufer
            _inputThread = new Thread(ReadInput)
            {
                Name = "PowerShellRawUi Input Thread"
            };
            _inputThread.Start(new Tuple <StreamConnection, ReadKeyOptions>(connection, options));

            // ReadInput will signal through this semaphore when a key has been pressed
            _inputSemaphore.WaitOne();
            connection.Capture = false;

            return(_readKey);
        }
        /// <summary>
        /// Wires up a PowerShell runspace created via <see cref="RunspaceFactory.CreateRunspace()"/> to the terminal to display the PowerShell to the user.
        /// </summary>
        public override void Connect()
        {
            GEnv.Options.Font = Connection.Font;

            _progressBar.Value  = 0;
            _progressLabel.Text = "";

            // This is not strictly a network connection:  we're relaying information that we receive from the runspace to the terminal over a local stream
            // (a StreamConnection in this case)
            TerminalParam terminalParam = TCPTerminalParam.Fake;

            terminalParam.TerminalType  = TerminalType.XTerm;
            terminalParam.RenderProfile = new RenderProfile();
            terminalParam.Encoding      = EncodingType.UTF8;

            StreamConnection connection = new StreamConnection(terminalParam)
            {
                Capture = false
            };

            ConnectionTag connectionTag = new ConnectionTag(connection);

            connectionTag.Receiver.Listen();

            // Attach the new "connection" to the terminal control
            _terminal.TerminalPane.FakeVisible = true;
            _terminal.TerminalPane.Attach(connectionTag);
            _terminal.TerminalPane.Focus();
            _terminal.TerminalPane.SendShiftTab = true;
            _terminal.SetPaneColors(Connection.TextColor, Connection.BackgroundColor);

            try
            {
                _powerShellHost = new PowerShellHost(this, _terminal, ExecuteQuiet, _progressBar, _progressLabel);

                // Create the host and runspace instances for this interpreter.  If we're connecting to the local host, don't bother with the connection info.
                // ReSharper disable StringCompareIsCultureSpecific.3
                if (String.Compare(Connection.Host, "localhost", true) != 0 && Connection.Host != "127.0.0.1" &&
                    String.Compare(Connection.Host, Environment.MachineName, true) != 0)
                // ReSharper restore StringCompareIsCultureSpecific.3
                {
                    WSManConnectionInfo connectionInfo = new WSManConnectionInfo
                    {
                        ComputerName = Connection.Host
                    };

                    if (!String.IsNullOrEmpty(Connection.InheritedUsername))
                    {
                        connectionInfo.Credential = new PSCredential(Connection.InheritedUsername, Connection.InheritedPassword);
                    }

                    Runspace = RunspaceFactory.CreateRunspace(_powerShellHost, connectionInfo);
                }

                else
                {
                    Runspace = RunspaceFactory.CreateRunspace(_powerShellHost);
                }

                Runspace.Open();
            }

            catch (Exception e)
            {
                OnConnectionLost(this, new ErrorEventArgs(e));
                return;
            }

            // Start capturing input from the prompt via the input loop
            _inputThread = new Thread(InputLoop)
            {
                Name = "PowerShellConnectionForm Input Thread"
            };
            _inputThread.Start();

            ParentForm.Closing += ParentForm_Closing;

            OnConnected(this, null);
        }
        /// <summary>
        /// Wires up a PowerShell runspace created via <see cref="RunspaceFactory.CreateRunspace()"/> to the terminal to display the PowerShell to the user.
        /// </summary>
        public override void Connect()
        {
            _progressBar.Value  = 0;
            _progressLabel.Text = "";

            // This is not strictly a network connection:  we're relaying information that we receive from the runspace to the terminal over a local stream
            // (a StreamConnection in this case)
            ITerminalParameter terminalParam = new EmptyTerminalParameter();
            StreamConnection   connection    = new StreamConnection(terminalParam)
            {
                Capture = false
            };

            // Attach the new "connection" to the terminal control
            try
            {
                ITerminalSettings terminalSettings = PoderosaTerminalEmulatorService.CreateDefaultTerminalSettings(Connection.DisplayName, null);
                TerminalSession   session          = new TerminalSession(connection, terminalSettings);
                SessionHost       sessionHost      = new SessionHost(PoderosaSessionManagerPlugin, session);
                TerminalView      terminalView     = new TerminalView(null, _terminal);
                RenderProfile     renderProfile    = new RenderProfile(_terminal.GetRenderProfile());

                renderProfile.BackColor = Connection.BackgroundColor;
                renderProfile.ForeColor = Connection.TextColor;
                renderProfile.FontName  = Connection.FontFamily;
                renderProfile.FontSize  = Connection.FontSize;

                session.TerminalSettings.BeginUpdate();
                session.TerminalSettings.RenderProfile = renderProfile;
                session.TerminalSettings.EndUpdate();

                _terminal.Attach(session);

                session.InternalStart(sessionHost);
                session.InternalAttachView(sessionHost.DocumentAt(0), terminalView);

                _powerShellHost = new PowerShellHost(this, _terminal, connection, ExecuteQuiet, _progressBar, _progressLabel);

                // Create the host and runspace instances for this interpreter.  If we're connecting to the local host, don't bother with the connection info.
                // ReSharper disable StringCompareIsCultureSpecific.3
                if (String.Compare(Connection.Host, "localhost", true) != 0 && Connection.Host != "127.0.0.1" &&
                    String.Compare(Connection.Host, Environment.MachineName, true) != 0)
                // ReSharper restore StringCompareIsCultureSpecific.3
                {
                    WSManConnectionInfo connectionInfo = new WSManConnectionInfo
                    {
                        ComputerName = Connection.Host
                    };

                    if (!String.IsNullOrEmpty(Connection.InheritedUsername))
                    {
                        connectionInfo.Credential = new PSCredential(Connection.InheritedUsername, Connection.InheritedPassword);
                    }

                    Runspace = RunspaceFactory.CreateRunspace(_powerShellHost, connectionInfo);
                }

                else
                {
                    Runspace = RunspaceFactory.CreateRunspace(_powerShellHost);
                }

                Runspace.Open();
            }

            catch (Exception e)
            {
                OnConnectionLost(this, new ErrorEventArgs(e));
                return;
            }

            // Start capturing input from the prompt via the input loop
            _inputThread = new Thread(InputLoop)
            {
                Name = "PowerShellConnectionForm Input Thread"
            };
            _inputThread.Start();

            ParentForm.Closing += ParentForm_Closing;

            OnConnected(this, null);
        }
Example #6
0
        /// <summary>
        /// Thread method invoked from <see cref="ReadKey"/> that waits for the user to press a key.
        /// </summary>
        /// <param name="state"><see cref="Tuple{T1, T2}"/> object containing a <see cref="StreamConnection"/> object and a <see cref="ReadKeyOptions"/>
        /// object.</param>
        private void ReadInput(object state)
        {
            StreamConnection connection       = (state as Tuple <StreamConnection, ReadKeyOptions>).Item1;
            ReadKeyOptions   options          = (state as Tuple <StreamConnection, ReadKeyOptions>).Item2;
            bool             inEscapeSequence = false;
            bool             readKey          = false;

            while (!readKey)
            {
                if (connection.OutputQueue.Count > 0)
                {
                    while (connection.OutputQueue.Count > 0)
                    {
                        byte currentByte = connection.OutputQueue.Dequeue();

                        // Handle the backspace key
                        if (currentByte == 8)
                        {
                            _readKey = new KeyInfo
                            {
                                VirtualKeyCode = 8
                            };

                            // If we're not already at the beginning of the line and we're echoing the output, move the cursor left
                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho && CursorPosition.X > 1)
                            {
                                CursorPosition = new Coordinates(CursorPosition.X - 1, CursorPosition.Y);
                            }

                            readKey = true;
                            break;
                        }

                        // The ^X character signifies the start of an ANSI escape sequence
                        else if (currentByte == 27)
                        {
                            inEscapeSequence = true;
                        }

                        // If we're in an escape sequence, read past the "[" and "~" characters
                        else if (currentByte == 91 && inEscapeSequence)
                        {
                        }

                        else if (currentByte == 126 && inEscapeSequence)
                        {
                        }

                        // ^X7 is the home key
                        else if (currentByte == 55 && inEscapeSequence)
                        {
                            _readKey = new KeyInfo
                            {
                                VirtualKeyCode = 0x24
                            };

                            // If we're not already at the beginning of the line and we're echoing the output, move the cursor to the start of the line
                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho)
                            {
                                CursorPosition = new Coordinates(1, CursorPosition.Y);
                            }

                            readKey = true;
                            break;
                        }

                        // ^X8 or ^X3 is the end key
                        else if ((currentByte == 56 || currentByte == 51) && inEscapeSequence)
                        {
                            _readKey = new KeyInfo
                            {
                                VirtualKeyCode = 0x23
                            };

                            // If we're not already at the beginning of the line and we're echoing the output, move the cursor to the end of the line
                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho)
                            {
                                CursorPosition = new Coordinates(BufferSize.Width, CursorPosition.Y);
                            }

                            readKey = true;
                            break;
                        }

                        // ^XD is the left arrow
                        else if (currentByte == 68 && inEscapeSequence)
                        {
                            _readKey = new KeyInfo
                            {
                                VirtualKeyCode = 0x25
                            };

                            // If we're not already at the beginning of the line and we're echoing the output, move the cursor left
                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho && CursorPosition.X > 1)
                            {
                                CursorPosition = new Coordinates(CursorPosition.X - 1, CursorPosition.Y);
                            }

                            readKey = true;
                            break;
                        }

                        // ^XC is the right arrow
                        else if (currentByte == 67 && inEscapeSequence)
                        {
                            _readKey = new KeyInfo
                            {
                                VirtualKeyCode = 0x27
                            };

                            // If we're not already at the beginning of the line and we're echoing the output, move the cursor right
                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho && CursorPosition.X < BufferSize.Width)
                            {
                                CursorPosition = new Coordinates(CursorPosition.X + 1, CursorPosition.Y);
                            }

                            readKey = true;
                            break;
                        }

                        // Handle the carriage return sequence
                        else if (currentByte == 13)
                        {
                            _readKey = new KeyInfo
                            {
                                Character      = '\r',
                                VirtualKeyCode = 0x0D
                            };

                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho)
                            {
                                CursorPosition = new Coordinates(1, CursorPosition.Y);
                            }

                            readKey = true;
                            break;
                        }

                        // Otherwise, get the virtual key code and character and populate _readKey
                        else
                        {
                            short            virtualKey  = User32.VkKeyScan((char)currentByte);
                            int              modifiers   = virtualKey >> 8;
                            ControlKeyStates controlKeys = 0;

                            if ((modifiers & 2) != 0)
                            {
                                controlKeys |= ControlKeyStates.LeftCtrlPressed;
                            }

                            if ((modifiers & 4) != 0)
                            {
                                controlKeys |= ControlKeyStates.LeftAltPressed;
                            }

                            _readKey = new KeyInfo
                            {
                                Character       = (char)currentByte,
                                VirtualKeyCode  = (virtualKey & 0xFF),
                                ControlKeyState = controlKeys
                            };

                            if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho)
                            {
                                _terminal.TerminalPane.ConnectionTag.Receiver.DataArrived(
                                    new byte[]
                                {
                                    currentByte
                                }, 0, 1);
                            }

                            readKey = true;
                            break;
                        }
                    }
                }

                // If we didn't read a key, sleep for a bit
                if (!readKey)
                {
                    Thread.Sleep(50);
                }
            }

            // Signal to ReadKey() that we've read a key
            _inputSemaphore.Set();
        }