Configuring the VSCode PowerShell Terminal

Yesterday I posted my experiences in setting up the latest build of VSCode on how to use a PowerShell terminal session. As I explained, in this particular session I didn’t want to run any profile scripts. My reasoning was that this session obviously wasn’t the ISE nor was I likely to use the session like I do the traditional console host. But, I also realized there were some tools and settings I would find useful. Obviously I didn’t want to manually configure the VSCode PowerShell session every time it started. It needed a profile script. Continue reading “Configuring the VSCode PowerShell Terminal”

Managing PowerShell Functions

Most of you probably know I’ve been using PowerShell since its beta days which now means I have about 10 years worth of PowerShell files. I find it hard to throw anything away. Over this time frame my PowerShell profile scripts have also grown, often loading functions that I’ve come up with. The effect has  been that it takes a little bit longer to bring up a new PowerShell console or ISE session. Since deep down I know there are functions I no longer use, I figured it was time for some profile cleanup. The first step was to identify my functions.

First, how many functions am I talking about? PowerShell stores currently defined and active functions in a PSDrive which means it is pretty easy to get a “directory” listing and count.

image

However, some of those functions are defined by Microsoft and other modules.

image

I don’t have any issues with functions defined from a given source. My problem is in that 100 that have no source.  Again some of those are defined by Microsoft which are fine. So I looked at one of them in more detail.

image

I noticed that these functions included a HelpFile. I knew that none of my functions didn’t. With this information I can get a directory listing and filter with Where-Object.

image

These are functions that are loaded from dot sourcing a ps1 file. By the way, the list had 62 items.

As an alternative I could use Get-Command which would get rid of any filters

Know that this will search for functions in modules not currently loaded so it takes a bit longer to run. This gave me 61 items.

But now at least I can go through the list and identify functions that I haven’t used in years or are now obsolete. Unfortunately, there’s no way to tell from the Function PSDrive or with Get-Command where the function came from.   Luckily I keep all my files in a single drive and most likely the function will be defined in a .ps1 script. I can use Select-String to find it.

In my list there is a function called Show-Balloon that I probably haven’t used in years. What file is it in?

I’m wrapping the function name in a regular expression word boundary so that I don’t get a match on something like show-balloontip. The –List parameter gives me the first match which is all I really need.

image

Because I write all of my functions with the same format, I could have searched like this and gotten the same result.

The output from Select-String is an object which includes a property for the filename or path.

image

Now I can put it all together.

I don’t want to have to re-list all the script files for every function, so I’ll get it once and then use that variable in the Select-Object expression.

image

With this information I can modify my PowerShell profiles and remove the lines that are loading the functions I don’t want or edit the source file to comment out the function if there was something else in the same file I did want to keep.  Any function in this list without a matching source is most likely defined directly in the profile script or will require a manual search.

Time now for a little housekeeping, although I’d love to hear how you keep things tidy in your PowerShell world.

Friday Fun: Create All PowerShell Profile Scripts

talkbubbleWhenever I train on PowerShell I inevitably get around to discussing PowerShell profile scripts. For those of you new to PowerShell, a profile script is where you put all the commands you want to run that will define your PowerShell session just the way you need it. You might load some snapins, create some PSDrives or define some variables. There are actually several profile scripts that can be run, depending on whether you are in the PowerShell console, the PowerShell ISE or some other PowerShell host.

The profile paths are hard-coded. You can see all of them by looking at the built-in $profile variable.

You can also look at just $profile which will show you the script for the current user on the current host. If you look at this in the ISE you’ll see some things are different.

ISE-Profiles

This variable is a bit tricky. Even though you can see properties here, if you pipe $profile to Get-Member all you get is a string definition. Here’s another way you can discover these.

Although I don’t really care about the length so let’s filter it out.

Now for the fun part. That value is a path so I can use Test-Path to see if it exists. If not, I can create the profile and at least indicate that is isn’t being used. Because most of these files don’t exist by default and in fact the WindowsPowerShell folder doesn’t exist under Documents until you create it, you might have to create the parent folder first. So I came up with a little script called Create-AllProfiles.ps1.

The script takes advantage of a feature in PowerShell 3 that will automatically enumerate properties. In PowerShell 2.0 I would need to do this:

But now in v3 and later I can do this:

The value property would show all of the values, including the length so because I’m getting an array, I can use a range of index numbers to select just the ones I want. In my script each value is tested and those that don’t exist are passed on to Foreach-Object.

For each path, I first split it so I can test if the parent path exists. If not, it is created. Then I create some text that will be inserted into each new profile script. The script supports -WhatIf so you can see what it would do before you run it for real.

create-allprofiles

I end up with a profile script that looks like this:

create-allprofiles-2

Ideally, I would recommend you digitally sign the profile scripts, assuming you are using an AllSigned execution policy, so that no changes can be made to these scripts without your knowledge. Just don’t forget to run this in the PowerShell ISE as well. If you have profiles already created, they will be ignored. And should you decide later to take advantage of any of the profile scripts, they are ready for you to edit.

Learn, enjoy and have a great weekend.

PowerShell Version Profiles

talkbubble One of the best things about PowerShell 3.0, for me anyway, is the ability to run PowerShell 2.0 side by side. I often need to test commands and scripts in both versions not only for my writing projects but also when helping people out. Like many of you I have a PowerShell profile script that configures my console. And because I primarily use PowerShell 3.0 I tend to have a number of version specific commands in my profile. The problem is that when I launch a PowerShell 2.0 session it uses the same profile, resulting in error messages for things it can’t do. So this is how I handle having a single profile that can be used by two different versions of PowerShell.

Basically, my profile script checks the version first, before doing anything. You can use the $psversiontable variable.

The PSVersion property is what I’m looking for. With this information, I can wrap my PowerShell profile script in simple IF statement.

I think the comments in the code sample are pretty clear and there’s really not much else to add. The Write-Host lines are merely for testing. You don’t really need them.

Now I can get properly configured PowerShell sessions regardless of version and without errors.

PowerShell Version Profile Tips

Now that PowerShell v3 is finally and officially with us, I’m trusting that many of you are embracing it. I’ve made the jump, although I have had to make some minor adjustments. If you are going to live entirely in a PowerShell v3 world, fantastic! Go forth and spread the news. But perhaps you are like me where there are still times you need to use PowerShell v2. Because of the material I develop, I often need to fall back to PowerShell v2. Fortunately this is easily done.


powershell -version 2.0

This assumes you have PowerShell 2 enabled as a feature which Windows 8 has by default. But that is just the start. I use PowerShell profile scripts extensively. When I start a v2 session, my profile scripts run. The problem is when they hit commands that are specific to v3. I could run my v2 session with -noprofile, but that defeats the purpose. I’ll come back to this in a moment. The first tweak I have made is to define a function in my profile script for the current user current host (ie the console) to automatically start a PowerShell v2 session. This way, whenever I start PowerShell, I automatically get a v2 session started.


Function New-V2Session {

Param([switch]$noprofile)

if ($NoProfile) {
Start-Process -file PowerShell.exe -arg '-version 2.0 -nologo -noprofile'

}
else {
Start-Process -file PowerShell.exe -arg '-version 2.0 -nologo'
}

} #end function

I can also use this function to launch future sessions with or without profiles. But I still need to manage both versions in the same profile script. Back to currentuser/currenthost, I have this code:


#kick off a clean v2 session if running v3
if ($psversiontable.psversion -eq "3.0") {
New-V2Session
}
Else {
#add v2 specific code
#set colors
$host.ui.rawui.ForegroundColor="Green"
$host.ui.rawui.BackgroundColor="black"
Clear-Host
} #else v2

When the v2 session is kicked off and the profile runs again, I change the colors of the v2 session to distinguish it. I could also insert any other v2 specific commands in the Else script block. For that matter, I could also insert any other v3 specific commands in the If script block. This is what I have done with another profile script, the one for current user/all hosts.


if ($psversiontable.psversion -eq "3.0") {
#run v3 specific commands
#update PowerShell help
. c:\scripts\Update-PowerShellHelp.ps1
Update-PowerShellHelp

$PSDefaultParameterValues=@{
"Send-MailMessage:From"="jhicks@jdhitsolutions.com"
"Send-MailMessage:To"="jhicks@jdhitsolutions.com"
}

} #if v3

This is code that runs whenever I start the console or the ISE. I don’t have any v2 specific commands but I am taking advantage of default parameter values. If the references to the updating help command intrigue you, take a look at an article I published on the Petri Knowledgebase.

The end result of all of this is I get properly setup sessions based on the PowerShell version. You may not need to use all the profile scripts that I am, but if you need to share profiles between versions, learn how to use $psversiontable.