PowerShell Problem Solver: Finding Orphan Aliases

Efficiency is paramount when working with the PowerShell console to get work done. Because there’s a lot of typing involved when working with PowerShell, there’s several features that intend to limit typing, such as tab completion for command and parameter names. Another ease-of-use feature is the PowerShell alias. Instead of typing Get-WmiObject, you can type a shortcut, gwmi. There’s nothing wrong with that. When it comes time to writing a script, however, the best practice is to use full cmdlet and parameter names. Another use of aliases is as transition-aids, which is demonstrated by using dir instead of having to use Get-ChildItem.

PowerShell automatically defines many aliases whenever you start a new session. You can also create your own aliases. You might do this for your own functions or even command-line tools. In my PowerShell profile, I have a command like this:

PowerShell

1

Set-alias–name np–value notepad.exe

At any time, I can type np and Notepad will launch. My PowerShell profile has grown over the years, and it has been moved around as I have changed computers. Recently I realized I had some aliases that were pointing to items that no longer existed. It doesn’t really matter if you have orphaned aliases, but I like things neat, so I decided that I needed a tool to test if an alias was still valid. I can use the Get-Alias cmdlet to get details.

Using get-alias to get details in Windows PowerShell. (Image Credit: Jeff Hicks)

As I expected np leads to notepad.exe. Let’s peak behind the curtain and see if there is anything else I can use.

Excellent. The definition property gives me the complete command. This is important because I can use Get-Command to verify it.

PowerShell

1

2

$a=Get-aliasnp

get-command-Name$a.Definition

Using get-command in Windows PowerShell. (Image Credit: Jeff Hicks)

That looks good and should mean that notepad.exe exists. But let’s test with something that I now will fail. I’ll create an alias that points to a non-existent command.

[Parameter(Position=0,Mandatory,HelpMessage="Enter the name of an alias",

ValueFromPipeline,ValueFromPipelineByPropertyName)]

[ValidateNotNullorEmpty()]

[string[]]$Name,

[switch]$Quiet

)

Begin{

Write-Verbose"Starting $($MyInvocation.Mycommand)"

}#begin

Process{

foreach($aliasin$Name){

Write-Verbose"Testing alias : $alias"

Try{

$def=(Get-Alias-Name$alias-ErrorActionStop).Definition

}

Catch{

Write-Warning"No alias found called $alias"

}

if($def){

Try{

Write-Verbose"Verifying command: $def"

if(Get-Command-Name$def-erroractionStop){

$tested=$True

}

}

Catch{

$tested=$False

}

if($Quiet){

Write$tested

}

else{

#write a custom object to the pipeline

[pscustomobject]@{

Name=$alias

Definition=$def

Test=$Tested

}

}

#clear $def so it doesn't get accidentally re-used

Remove-Variable-NameDef

}#if $def

}#foreach

}#process

End{

Write-Verbose"Ending $($MyInvocation.Mycommand)"

}#end

}#end Test-Alias

#create an alias

Set-Alias-Nameta-ValueTest-Alias

Test-Alias Help. (Image Credit: Jeff Hicks)

You can test an alias by name.

Testing the alias in PowerShell by name. (Image Credit: Jeff Hicks)

Or you can pipe names to it.

Piping a name to the alias. (Image Credit: Jeff Hicks)

The default behavior is to write a custom object to the pipeline, but I also thought there might be a time when you want to test and need a simple Boolean result. Test-Connection works the same way.

If you were scripting with my function, then this means you could write a simple if statement like this:

PowerShell

1

2

3

If(test-aliasls){

#found

}

But I don’t need a script to validate all of my aliases. I can do it from the console.

PowerShell

1

get-alias|test-alias|where{-Not$_.Test}|format-table–AutoSize

Validating alias from the console. (Image Credit: Jeff Hicks)

Now I know what to clean up. Although I can’t tell where these aliases were defined, if you want to test aliases defined in your profile, start a new PowerShell session and run Test-Alias.

There are a few caveats with Test-Alias. Because it uses Get-Command, if you have an alias that points to a command in a module that isn’t currently loaded in your session, that module will be loaded during the process of using Test-Alias.

As an example, let’s say I have an alias called gau that points to Get-ADUser from the ActiveDirectory module. PowerShell will load the ActiveDirectory module during the process of testing the alias. This is because of PowerShell’s autoloading feature introduced in PowerShell 3.0. This also means that any alias that point to commands in a PSSnapin, will fail to properly resolve, unless you first manually add the PSSnapin.

Even if you don’t need to test aliases, I hope you learned a few thing about creating PowerShell tools. As always I’d love to hear what you think.

MEMBER LOGIN:

BECOME A PETRI MEMBER:

About the Contributor

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, teacher and consultant. Jeff has written for numerous online sites and print publications and is a frequent speaker at technology conferences and user groups. His latest book is PowerShell Scripting and Toolmaking.