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.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
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.
However, some of those functions are defined by Microsoft and other modules.
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.
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.
dir function: | where {(-Not $_.Source) -AND ($_.HelpFile -notmatch "System\.Management")}
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
get-command -CommandType function | where {(-Not $_.Source) -AND ($_.HelpFile -notmatch "System\.Management")}
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?
dir c:\scripts\*.ps1 | select-string "\bshow-balloon\b" –List
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.
Because I write all of my functions with the same format, I could have searched like this and gotten the same result.
dir c:\scripts\*.ps1 | select-string "\bFunction show-balloon\b" –List
The output from Select-String is an object which includes a property for the filename or path.
Now I can put it all together.
$scripts = dir c:\scripts\*.ps1 dir function: | where {(-Not $_.Source) -AND ($_.HelpFile -notmatch "System\.Management")} | Select Name,@{Name = "Source";Expression = { ($scripts | select-string "\b$($_.name)\b" -list).Path}}
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.
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.