9

To make it more obvious when I'm remoted to a live/production server, I thought it'd be handy to be able to colour the machine name I'm connected to when using remote PowerShell sessions.

However, I can't see a way to do this... The server name prefix seems to be independent of the Prompt function, and even if I could use that, I'm not sure how I could define a new Prompt only for the duration of the session.

Is there a way to customise this? Note: I don't want to color all server names the same, I'd like a distinction between local/production servers.

Danny Tuppeny
  • 40,147
  • 24
  • 151
  • 275

2 Answers2

6

After some searching around it seems like you are correct that there is not built-in hook to override the pre-prompt [computername]: tag.

Luckily, I have a hacky workaround which could work for you!

To get color, we can just use Write-Host. Write-Host output from the prompt function will be fully left-justified, which is what we want. Unfortunately, the default [computername]: tag is inserted directly afterward. That results in the computer name being duplicated in the prompt, once with color and once without.

We get around this by returning a string containing backspace characters, so the un-colored [computername]: will be overwritten. This is the normal prompt string, typically the current path.

Finally, in case the normal prompt string is short and does not fully overwrite the un-colored [computername]: tag, we need to do some final cleanup by adding dummy space characters. That might push out the caret, though, so we need to add more backspaces to return the caret to the corrent position.

All-up, use this on your remote machine:

# put your logic here for getting prompt color by machine name
function GetMachineColor($computerName)
{
   [ConsoleColor]::Green
}

function GetComputerName
{
  # if you want FQDN
  $ipProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
  "{0}.{1}" -f $ipProperties.HostName, $ipProperties.DomainName

  # if you want host name only
  # $env:computername
}

function prompt
{
  $cn = GetComputerName

  # write computer name with color
  Write-Host "[${cn}]: " -Fore (GetMachineColor $cn) -NoNew

  # generate regular prompt you would be showing
  $defaultPrompt = "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "

  # generate backspaces to cover [computername]: pre-prompt printed by powershell
  $backspaces = "`b" * ($cn.Length + 4)

  # compute how much extra, if any, needs to be cleaned up at the end
  $remainingChars = [Math]::Max(($cn.Length + 4) - $defaultPrompt.Length, 0)
  $tail = (" " * $remainingChars) + ("`b" * $remainingChars)

  "${backspaces}${defaultPrompt}${tail}"
}
latkin
  • 16,402
  • 1
  • 47
  • 62
  • Slight problem with this; if the computer is remote and has a name like mycomputer.mydomain.com then it seems to mess up; presumably because $env:ComputerName is only the local part? – Danny Tuppeny Dec 04 '12 at 10:35
  • Yes, `$env:ComputerName` is just the hostname. I believe the tag Powershell adds matches the string you pass to `Enter-PsSession -ComputerName`. That is, if you only give the hostname, it will only show the hostname, even for a domain-joined box. If you chose to fully qualify it, Powershell will print the fully qualified name. All of this prompt code is running on the remote box, which doesn't have any way of knowing which option you might have picked. – latkin Dec 04 '12 at 14:03
  • Found a niec way to fix this; my helper connection function can just pass the host used to connect in to the remote session, which can then be used by the prompt function (if defined) `Invoke-Command -Session $session -ScriptBlock { $connectedHost = $using:remoteHost }` – Danny Tuppeny Dec 05 '12 at 08:36
0

I use Posh-Git to accomplish this. See their Prompt Customization. I noticed that some of the docs are a bit out of date, if you just type $GitPromptSettings in PowerShell you will see all the properties available. Using Posh-Git has the added bonus of seeing Git stats on the prompt.

The command I use to set the machine name is ...

$GitPromptSettings.DefaultPromptPrefix = '$(get-content env:computername) '

Here is the color setting

$GitPromptSettings.DefaultPromptPath.ForegroundColor = 'Orange'

JabberwockyDecompiler
  • 3,318
  • 2
  • 42
  • 54