Lessons in PowerShell - Variables and Declarations

The following useful information is primarily taken from the Windows PowerShell Language Quick Reference (QuadFold.rtf) documentation.

Automatic Variables

PowerShell includes the following in-built variables:

Variable Description
$$ Last token of the previous command line
$? Boolean status of last command
$^ First token of the previous command line
$_ Current pipeline object
$Args Arguments to a script or function
$Error Array of errors from previous commands
$Foreach Reference to the enumerator in a foreach loop
$Home The user’s home directory; usually set to %HOMEDRIVE%%HOMEPATH%
$Host Reference to the application hosting the POWERSHELL language
$Input Enumerator of objects piped to a script
$LastExitCode Exit code of last program or script
$Matches Hash table of matches found with the -match operator
$PSHome The installation location of Windows PowerShell
$profile The standard profile (may not be present)
$StackTrace Last exception caught by Windows PowerShell
$Switch Enumerator in a switch statement
$True Boolean True
$False Boolean False
$Null Null

Variable Declaration

Variables and other data elements may be instantiated in different scopes:

  • Variables in the global scope are visible in all scopes.
  • Variables in the script scope are visible to all scopes within that script file.
  • Variables in the local scope are visible only in the current scope and its children.
  • Private scope variables are visible only to that current scope.

A scope is created in the body of a shell function.

Format:

1$[scope:]name or ${anyname} or ${any path}

Examples:

1$a = 1
2$global:a = 1    # Visible everywhere
3$local:a = 1    # defined in this scope and visible to children
4$private:a=1    # same as local but invisible to child scopes
5$script:a=1    # visible to everything in this script
6$env:path = "d:\windows"
7${C:\TEMP\testfile.txt}="This writes to a file"
8Get-Variable -scope 1 a    #Gets value from the parent scope
9Get-Variable -scope 2 a    # grandparent

Type Declaration

Variables also can be declared as specific data type by prefixing the variable declaration with the data type.

Type Description
[bool] or [boolean] A boolean (True or False) value
[byte] An 8-bit unsigned character
[char] A Unicode 16-bit character
[string] String of Unicode characters
[datetime] A System.DateTime object
[int] A 32-bit signed integer
[long] A 64-bit signed integer
[single] A Single-precision 32-bit floating point number
[double] Double-precision floating number
[decimal] A 128-bit decimal value
[xml] A xml object
[array] An array of values
[hashtable] A System.Collections.Hashtable object
[wmi] Windows Management Instrumentation (WMI) instance or collection
[wmiclass] WMI class
[adsi] Active Directory Services object

A variable’s type also can be declared as a .NET Framework class by using the full class name. For example:

1[System.Int32] $amount = 1234

Lessons in Windows PowerShell - Hello World

A “Hello World” script is probably a good starting point.

Start PowerShell from Start Menu ➞ All Programs ➞ Windows PowerShell 1.0 ➞ Windows PowerShell.

At the PowerShell command prompt, the command Help shows the various commands and aliases that are available in PowerShell.

The command Write-Host Hello World will essentially do the same as the old Command Prompt echo command - which is great for our purpose here. But that is too easy… we want a script!

In a text editor, create a text file named “test.ps1” and save it to the current path within PowerShell. Add the following text to the file and save it.

1Write-Host Hello World

Back in the PowerShell window, how do we run the script?

Just typing the command test.ps1 produces the following error.

1The term 'test.ps1' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
2At line:1 char:8      
3+ test.ps1 <<<<

Instead, the name of the script needs to be prefixed with a period followed by a forward or backwards slash.

Run the command ./test.ps1.

Since we haven’t digitally signed the script, another error appears.

1File test.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.
2At line:1 char:10      
3+ ./test.ps1 <<<<

This error occurs because by default the execution policy that affects all users on a machine is set (in the Windows Registry) such that unsigned scripts are disabled.

The command Get-ExecutionPolicy shows the current policy about executing scripts. Currently it is set to “Restricted”.

The command Get-Help Set-ExecutionPolicy provides general information about the Set-ExecutionPolicy command.

The command Get-Help Set-ExecutionPolicy -detailed provides more detailed information about the Set-ExecutionPolicy command.

The command Get-Help Set-ExecutionPolicy -full provides the most information about the Set-ExecutionPolicy command.

The command Set-ExecutionPolicy -executionPolicy RemoteSigned will set the policy such that only scripts that are downloaded from the internet are required to be signed by a trusted publisher.

However, on Windows Vista the following error occurs because it requires escalated privileges.

1Set-ExecutionPolicy : Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1ShellIds\Microsoft     
2.PowerShell' is denied.      
3At line:1 char:20      
4+ Set-ExecutionPolicy <<<< -executionPolicy RemoteSigned

The easiest way to change the execution policy in Vista is to start PowerShell from the start menu by right-clicking and selecting “Run as Administrator”. From within that PowerShell the Set-ExecutionPolicy command will work. Close that window after executing the command.

Finally we can then successfully execute the script with the command ./test.ps1, and it actually works!

Lessons in Windows PowerShell - Introduction

One of our Team Foundation Server build servers recently ran out of disk space. Upon closer investigation, we had 6 team projects building on that server, each with at least 3 different code branches, totalling more than 18 build folders - with each build folder larger than 2Gb. Do the maths, and that is essentially more than 40Gb being used.

Those folders however are not needed after a build has completed, and they can be safely deleted - so I decided that I would write a Windows PowerShell script to delete folders that haven’t been written to for more than a day, and schedule the script to run through the Windows Task Scheduler.

Well, there was only one problem… I haven’t really used PowerShell before. But, a couple of hours later, and I had the solution.

The start of this series of lessons reflects some of the lessons I quickly learned.

Refer to the official Powershell documentation for more information.