Tag Archives: TLS

Change Prompt on Module Import

To me, my PowerShell prompt is quite important. I’ve written about it nine times already. While I’m not going to write about it again, so much, I am going to focus on an updated prompt I’ve created for a recent project. I couldn’t help but take a few things into this project from my prompt, and that’s why that’s been mentioned.

I recently received a screen capture from someone running into a problem using one of the tools I’ve written. Sure, it needs some error checking, I won’t deny that, but it was a very obscure and unforeseen problem. You know, how we often find out about error conditions.

This tool, or function, can be run on an Amazon Web Services EC2 instance within a project, to determine the status of its partner EC2 instance. When it works, it returns the status of the other instance, to include things like running, stopping, stopped, etc. There’s also a couple other companion functions that can start and stop the partner instance. The second of the two machines has very high specifications, and so we ask that our users shut down those secondary instances when they’re not running experiments. They pricey.

The problem is that when I look at this error, the prompt doesn’t tell me enough. I can only tell it’s PowerShell — the PS in the prompt — and the current path — some of which has been hidden in this first image. I want more information without having to ask the user, and so I’ve added that in.  Here’s the default prompt up close.

The new prompt includes the username (to the left of the @), the computer name (to the right of the @), the project name (while it’s not in this example, it’s normally a part of the computer name), the path, and whether the user is an admin (#) or not ($). Now, when I receive a PowerShell screen capture, I already have a few of my first questions answered.

All of the functions, such as the one that was run that generated this error, are a part of the same PowerShell module. There’s somewhere near 20 of them so far, and I keep finding reasons to add new ones. If you don’t know, creating a PowerShell script module that includes a module manifest file (a .psd1), allows one to include scripts that execute just before a module is imported. This, whether the module is imported manually using Import-Module, or by invoking a function from within the module, when the module hasn’t yet been imported.

Let’s take a look at my SetPrompt.ps1 script file that executes when my PowerShell module is imported.

Function prompt {
    # Determine Admin; set Symbol variable.
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'} Else {$Symbol = '$'
    }

    # Create prompt.
    "[$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $($executionContext.SessionState.Path.CurrentLocation)]$Symbol "
} # End Function: prompt.

With this script in place and a ScriptsToProcess entry in the module’s manifest file, pointing to this file, I can be ensured that the user’s prompt will change the moment my module is imported. From here on out, I can rest assured that if a user — of these machines at least — sends us a screen capture that it’ll include relevant pieces of information I would have had to ask for, had this prompt not been in place.

There’s a final thought here. When the user is done with this PowerShell module, they’re still going to have this prompt. In my case, it’s perfectly suitable because my users won’t be in PowerShell, unless they’re issuing commands from the module. At least, I can’t imagine they will be. The only other thoughts I’ve had about this “problem” would be to (1) teach users to remove the module, and have code in the prompt monitor whether the module is loaded or not, and revert the prompt if the module is removed, or (2) revert the prompt if a command outside of my module is invoked.

That’s it for today. I don’t have it shown here, but it’s neat to see the prompt alter itself when the module is loaded. Something to keep in mind, if you find yourself in a similar situation.

Update: I was annoyed that $HOME, or C:\Users\tommymaynard, was being displayed as the full path, so I made some additional modifications to the prompt that’s being used for this project. It’ll now look like this, when at C:\Users\tommymaynard (or another user’s home directory).

Here’s the new prompt function, to include a better layout.

Function prompt {
    # Determine Admin; set Symbol variable.
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'
    } Else {
        $Symbol = '$'
    }

    If ((Get-Location).Path -eq $env:USERPROFILE) {
        $Path = '~'
    } Else {
        $Path = (Get-Location).Path
    }

    # Create prompt.
    "[$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $Path]$Symbol "
} # End Function: prompt.