Beware of Aliases

Can you spot what is wrong here?

 
PS C:> function r { "This never runs" }

PS C:> r
function r { "This never runs" }

PS C:>
 

When you run function “r”, it simply returns the function source code.

The reason is that the function name “r” conflicts with a built-in alias:

 
PS C:> Get-Alias r

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------                                        
Alias           r -> Invoke-History                                                                                     


PS C:>
 

So always make sure you know your built-in alias names – they always have precedence over functions or any other command. Better yet, adhere to best practice, and always assign Verb-Noun names to your functions.

Twitter This Tip! ReTweet this Tip!

Dealing with Long File Paths

Historically, the Windows file system sometimes stalls when paths grow longer than 256 characters. There is a module available at the PowerShell Gallery that adds cmdlets to quickly search the file system, and support paths of any length.

If you use PowerShell 5 or have installed PowerShellGet (www.powershellgallery.com), this is how you can download and install the “PSAlphaFS” module from the PowerShell Gallery:

 
Install-Module -Name PSAlphaFS -Scope CurrentUser 
 

Unfortunately, the cmdlets seem to require full Administrator privileges and throw exceptions for regular users. As an Administrator, you can now run commands like this to find files with critical path length:

Get-LongChildItem -Path c:windows -Recurse -File |
  Where-Object { $_.FullName.Length -gt 250 }

Twitter This Tip! ReTweet this Tip!

Detecting Character Code 0

Occasionally, strings use a “Byte 0” character as a delimiter. Unlike most other delimiters, this delimiter does not show in text output but can still be used to separate the text parts.

PowerShell can deal with character code 0 strings. It is represented by a backtick followed by the number 0. Note that text needs to be placed in double-quotes in order to convert the backtick sequence to byte 0.

Here is an example illustrating how you split text that uses code 0 as delimiter:

# create a sample text
$text = "Part 1`0Part 2`0Part 3"
# delimiter does not show in output...
$text 
# ...but can be used to split:
$text -split "`0"

Twitter This Tip! ReTweet this Tip!

Auto-Declaring Alias Names for Functions

You probably know that PowerShell supports alias names for commands. But did you know that you can define alias names for PowerShell functions inside a function definition (introduced in PowerShell 4)? Have a look:

function Get-AlcoholicBeverage
{
    [Alias('Beer','Drink')]
    [CmdletBinding()]
    param()

    "Here is your beer."
}

The “official” name for the function is Get-AlcoholicBeverage, but this function is also available via the aliases “Beer” and “Drink”. PowerShell automatically adds these aliases when the function is defined:

 
CommandType     Name                                              
-----------     ----                                                                                       
Alias           Beer -> Get-AlcoholicBeverage                                                                               
Alias           Drink -> Get-AlcoholicBeverage
 

Twitter This Tip! ReTweet this Tip!

Checking Operating System Version

Here is a simple and fast way of checking the operating system version:

 
PS C:> [Environment]::OSVersion


Platform ServicePack Version      VersionString                    
-------- ----------- -------      -------------                    
 Win32NT             10.0.14393.0 Microsoft Windows NT 10.0.14393.0
 

So now it’s a snap checking whether a script runs on the intended operating system. To check for Windows 10, for example, try this:

 
PS C:> [Environment]::OSVersion.Version.Major -eq 10

True
 

Twitter This Tip! ReTweet this Tip!

Comparing Against $NULL

If you want to find out whether a variable contains $Null (nothing), always make sure you keep $null on the left side of the comparison. Most of the time, the order does not really matter:

 
PS C:> $a = $null

PS C:> $b = 12

PS C:> $a -eq $null
True

PS C:> $b -eq $null
False
 

However, if a variable contains an array, placing the array on the left side of the comparison operator makes it work like a filter. So now order becomes vital:

# this all produces inconsistent and fishy results
 
$a = $null
$a -eq $null  # works: returns $true
 
$a = 1,2,3
$a -eq $null  # fails: returns $null
 
$a = 1,2,$null,3,4
$a -eq $null  # fails: returns $null
 
$a = 1,2,$null,3,4,$null,5
$a -eq $null  # fails: returns array of 2x $null
($a -eq $null).Count

If you place the variable on the left side, PowerShell checks for $null values inside the array and returns these, or $null if there are no such values.

If you place the variable on the right side, PowerShell checks whether the variable is $null.

# by reversing the operands, all is FINE:
 
$a = $null
$null -eq $a  # works: $true
 
$a = 1,2,3
$null -eq $a  # works: $false
 
$a = 1,2,$null,3,4
$null -eq $a  # works: $false
 
$a = 1,2,$null,3,4,$null,5
$null -eq $a  # works: $false

This can be eliminated by placing $null on the left rather than on the right side of the comparison.

Twitter This Tip! ReTweet this Tip!