~stick/stma.is

ee0b67006b97851deddb7d5ca7ec8ab7d2df2044 — Stick 7 months ago c31ca5a
ssh to powershell notes
1 files changed, 66 insertions(+), 0 deletions(-)

A content/stick/2022-02-08-ssh-to-powershell.md
A content/stick/2022-02-08-ssh-to-powershell.md => content/stick/2022-02-08-ssh-to-powershell.md +66 -0
@@ 0,0 1,66 @@
---
title: "SSH to PowerShell"
author: "Stick"
date: 2022-02-08
---

Last week I needed to work in PowerShell on a set of remote machines.
No problem; the machines had [ssh installed](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse)!
First problem: SSH dumps you into a command prompt, not PowerShell, so you need to run `powershell` on login every time.
Thankfully, [`~/.ssh/config`](https://www.man7.org/linux/man-pages/man5/ssh_config.5.html) (since [version 7.6](https://www.openssh.com/txt/release-7.6)) has an option to do this:

```
Host windows_server
    RemoteCommand powershell
```

It works!
But: problem!
I use a dark theme.
The defaults for [PSReadLine](https://docs.microsoft.com/en-us/powershell/module/psreadline/?view=powershell-7.2) make the "Operator" and "Parameter" tokens _dark gray_, also known as _invisible_ or at least _[heavily obscured](https://roleplayersrespite.com/heavily-obscured-5e)_ against a dark background.
Using [`Get-PSReadLineOption`](https://docs.microsoft.com/en-us/powershell/module/psreadline/get-psreadlineoption) shows the full colorscheme (and other options).
[Tim Abell](https://timwise.co.uk/) has a [StackOverflow answer](https://stackoverflow.com/a/41954792) with a script to show all the console colors; I don't care about seeing each on a different background so I simplified it.

```powershell
Foreach ($fgcolor in [enum]::GetValues([System.ConsoleColor])) { Write-Host "$fgcolor | " -ForegroundColor $fgcolor -NoNewLine }
```

We can use [`Set-PSReadLineOption`](https://docs.microsoft.com/en-us/powershell/module/psreadline/set-psreadlineoption) to change the colors, but once again that means running another command (and a much longer one) after login.

```powershell
Set-PSReadLineOption -Colors @{
  Member=\"$([char]0x1b)[95m\";
  Number=\"$([char]0x1b)[94m\";
  Operator=\"$([char]0x1b)[97m\";
  Parameter=\"$([char]0x1b)[97m\";
  Type=\"$([char]0x1b)[34m\";
  Variable=\"$([char]0x1b)[35m\"
}
```

I changed more than just "Operator" and "Parameter" colors to make things a little nicer.

The next step is to cause PowerShell to run this command immediately after login.
Note that besides the [`-Command` flag](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1#-command) (which must be _last_), we also need the `-NoExit` flag so that PowerShell does not immediately quit (ending our ssh session) after setting the proper colors.

```
Host windows_server
    RemoteCommand powershell -NoExit -Command Set-PSReadLineOption -Colors @{ Member=\"$([char]0x1b)[95m\"; Number=\"$([char]0x1b)[94m\";  Operator=\"$([char]0x1b)[97m\"; Parameter=\"$([char]0x1b)[97m\"; Type=\"$([char]0x1b)[34m\"; Variable=\"$([char]0x1b)[35m\" }
```

I found that this worked on the most up-to-date servers, but there were some older machines in the environment, and the `Set-PSReadLineOption` command as written threw errors there.
A few machines still had PSReadLine version 1, which [used a different syntax to set colors](https://github.com/PowerShell/PSReadLine/blob/0674f91a8e4ded1f1f2ec5175abfc1c5b39377a9/PSReadLine/Changes.txt#L33).

```
Host old_windows_server
    RemoteCommand powershell -NoExit -Command Set-PsReadLineOption -TokenKind None -ForegroundColor White; Set-PsReadLineOption -TokenKind Member -ForegroundColor Magenta; Set-PsReadLineOption -TokenKind Number -ForegroundColor Blue; Set-PsReadLineOption -TokenKind Operator -ForegroundColor White; Set-PsReadLineOption -TokenKind Parameter -ForegroundColor White; Set-PsReadLineOption -TokenKind Type -ForegroundColor DarkBlue; Set-PsReadLineOption -TokenKind Variable -ForegroundColor DarkMagenta
```

Some others, which seemed to be up-to-date, also did not like the special character syntax so I used color names.

```
Host other_windows_server
    RemoteCommand powershell -NoExit -Command Set-PSReadLineOption -Colors @{ Member='Magenta'; Number='Blue';  Operator='White'; Parameter='White'; Type='DarkBlue'; Variable='DarkMagenta' }
```

Using the color names instead of VT escape sequences seemed to work on all the machines, but according to the documentation [any number of methods](https://docs.microsoft.com/en-us/powershell/module/psreadline/set-psreadlineoption?view=powershell-7.2#example-5--set-color-values-for-multiple-types) are acceptable, so ¯\\\_(ツ)\_/¯.