Tag Archives: Enter-PSSession

Add a Dynamic Number of Asterisks

Recently, on a Windows PowerShell forum, a person wanted a script to run each time they connected to a PowerShell remote endpoint — such as a local profile does when you open the PowerShell, console host. I recommended a couple options: Create a new endpoint, and use a ScriptsToProcess .ps1 file, or modify the default, Microsoft.PowerShell endpoint, using the Set-PSSessionConfiguration cmdlet.

To use the second option I recommended, you need to add a start up script, such as the example below does. Keep in mind that you can name the .ps1 file anything you’d like. That said, I typically name these files so that I’m certain what they go with — such as, which endpoint.

PS> Set-PSSessionConfiguration -Name Microsoft.PowerShell -StartUpScript C:\Microsoft.PowerShell.StartUpScript.ps1

In order to test my updated, Microsoft.PowerShell endpoint (on my desktop computer), I decided I would add a couple informational lines of text to the script. One would indicate the “remote” computer’s name, and the other would provide the date and time. Here’s that output.

PS> Enter-PSSession -ComputerName . # This dot indicates the local computer
You are connected to TOMMYSCOMPUTER.
6/11/2015 21:17:15 PM
[localhost]: PS C:\>

As I stared at this, I decided I would prefer that the date and time was centered under the first line, with asterisks on either side, so that both lines were the same length. This means I would need to dynamically determine how many asterisks I would need on each side of my date and time, so that the asterisks, and the date and time text, would fill up as much space as the line above. It was a new PowerShell challenge, and so I ran with it.

Before we go further, let me start by showing you an image of the end results, in case the explanation wasn’t clear. Then, we’ll walk though what I did to accomplish this task.

Add-a-Dynamic-Number-of-Asterisks-2015-01

I’ve broken down my start up script into five different parts. As you’ll see, I did things very procedurally. I wasn’t worried about using a minimal amount of commands and variables. For those with more experience, you’ll easily see how things could have been much tidier. Let’s start with the first two lines.

$Computer = "You are connected to $env:COMPUTERNAME."
$Date = Get-Date -Format G

These two lines set one variable each: $Computer and $Date. Each of these values will be used in the next example.

$TopLength = $Computer.Length
$BottomLength = $Date.Length

This section, above, determines and stores the character length of the $Computer and $Date variables. We are going to need to add asterisks for the difference between these two lengths.

$DiffInLength = $TopLength - $BottomLength
$Before = [math]::Round($DiffInLength/2)
$After = $DiffInLength - $Before

This third section puts the difference between $TopLength and $BottomLength into a variable called $DiffInLength. It then creates a $Before variable to store 1/2 of $DiffInLength — it will round up, if this amount isn’t a whole number. It then creates an $After variable, which will hold the leftovers from the previous calculation.

$Before = '*' * $Before
$After = '*' * $After

Next, as seen above, we’ll overwrite our $Before and $After variables with new values. Each of those values will be a set of asterisks. How do we know how many? We multiply the asterisk symbol (a string character) by the numeric values stored in the $Before and $After variables.

Write-Host -Object $Computer -ForegroundColor Green
Write-Host -Object $Before$Date$After -ForegroundColor Green

If you’re still following along, we then write out our two lines. The first line is made up of the $Computer variable. Following that line, we write our first set of asterisks, the date, and then the second set of asterisks.

This might have been a lot to take in, so you may consider copying and pasting each line into your PowerShell host and watch as it creates the two lines for you. Regardless of the length of your computer name, your two lines will be the same length, too.

Now, that last statement isn’t always true. What if we changed $Computer to just be the computer name, such as $Computer = $env:COMPUTERNAME? I know what happens; it’s throws errors and won’t let you connect to the endpoint. This problem begins with us subtracting a larger number from a smaller number. I’ve added some logic to skip a good portion of our script, if the $TopLength is smaller than $BottomLength. I’ve include the full script below.

$Computer = "You are connected to $env:COMPUTERNAME."
$Date = Get-Date -Format G

$TopLength = $Computer.Length
$BottomLength = $Date.Length

If ($TopLength -gt $BottomLength) {
    $DiffInLength = $TopLength - $BottomLength
    $Before = [math]::Round($DiffInLength/2)
    $After = $DiffInLength - $Before
    $Before = '*' * $Before
    $After = '*' * $After
}

Write-Host -Object $Computer -ForegroundColor Green
Write-Host -Object $Before$Date$After -ForegroundColor Green

In case someone wants to a see a tidier version of this same script, then here it is. We still use the $Before and $After variables, but no others, outside of our $Computer and $Date variables.

$Computer = "You are connected to $env:COMPUTERNAME."
$Date = Get-Date -Format G

If ($Computer.Length -gt $Date.Length) {
    $Before = '*' * ([math]::Round(($Computer.Length - $Date.Length)/2))
    $After = '*' * $Before.Length
}

Write-Host -Object $Computer -ForegroundColor Green
Write-Host -Object $Before$Date$After -ForegroundColor Green

 

Out-GridView in a PSRemoting Session

Twitter Reply to:

We can’t use the Out-GridView cmdlet in a remote session. How do we know this? Well for one, the documentation says so (search for ‘You cannot use a remote command’ on that webpage), and two, because if you try, you’ll get a straight forward error message on the topic: “Out-GridView does not work in a remote session.” Okay, but why?

Out-GridView produces a Graphic User Interface (GUI) — something we don’t use in PSRemoting sessions. In fact, everything about a PSRemoting session is text only. This isn’t just about Out-GridView, though. Other graphical elements in Windows PowerShell aren’t going to work either. This includes Get-Help’s -ShowWindow parameter, and the Show-Command cmdlet. It just wasn’t designed to work this way.

Other GUI elements don’t work either. While you won’t get a helpful message, like you do with the PowerShell cmdlets and parameters, launching notepad.exe and calc.exe isn’t going to work like it does on a local computer. Those programs work a little differently though, as they will actually launch on the remote computer. It just won’t be in any useable fashion from your remote session. Bonus: They may lock up your remote session until they are closed.

Note: If you were to try this, one way to rectify the situation would be to open a second PowerShell console and run the following, assuming you launched calc.exe: Invoke-Command -ComputerName computername -ScriptBlock {Get-Process -Name calc.exe | Stop-Process}. This would end the process on the remote computer, and give you back your prompt on the console where you were running your PSRemoting session.

Everything until now, assumed we were talking about an interactive PSRemoting session (using the Enter-PSSession cmdlet). Well, what about Invoke-Command? Invoke-Command is used to run commands on remote systems and return the results to the local computer. As you can see in the examples below, we can run a command on a remote computer and then display the results on our local computer, inside Out-GridView.

Note: Although I didn’t have any problems with the small handful of cmdlets I tried, the same webpage linked above indicates that data returned from a remote computer may not be formatted correctly for use with Out-GridView.

PS C:\> $Services = Invoke-Command -ComputerName dc01 -ScriptBlock {Get-Service}
PS C:\> $Services | Out-GridView
PS C:\> $PSWARules = Invoke-Command -ComputerName PSWAServer01 -ScriptBlock {Get-PSWAAuthorizationRule}
PS C:\> $PSWARules | Out-GridView

Thanks for the inspiration to write a little about this topic, Tim.