Writing Scripts

While you can use the PowerShell prompt to run cmdlets, most Windows Server 2008 administrators will write their own scripts for performing tasks in their environment. For example, you could develop a script to ping remote systems to discover whether they are available, and report on those that are not. You could extend this to time how long a ping takes and report whether that time is outside of some previously established norm, or you could develop a script to add a user to your active directory, add the users to role-based security groups, enable the Exchange and Unified messaging mailboxes, and enable the user to use the Office Communications server.

A script is a text file with a PS1 extension that contains the commands you might type at the PowerShell prompt along with a variety of control statements to control the execution of your script. In general, there is nothing you can do in a script that you could not do at the PowerShell prompt—scripts just cut down on typing. This means you can try things out at the PowerShell prompt, and create your script from there—something not really possible in traditional scripting languages such as VBScript.

For added security, scripts can be digitally signed. When combined with PowerShell's execution policy, this enables you to restrict administrators to only running scripts specifically signed by your organization. For more information about signing PowerShell scripts, see http://www.hanselman.com/blog/SigningPowerShellScripts.aspx.

The world's shortest Hello World script would be a file, helloworld.ps1, as follows:

PSH [D:\foo]: cat helloworld.ps1
"Hello World"
PSH [D:\foo]: .\helloworld.ps1
Hello World
PSH [D:\foo]:

This very short script just displays the string "Hello World". It is not particularly useful. Production scripts tend to do more than just output "Hello World". Here's a more functional script that displays the size of each disk (including mapped network drives), along with the amount of free space available:

PSH [D:\foo]:cat get-disksize.ps1
#get-disksize.ps1
#Thomas Lee tfl@psp.co.uk
Param ($Computer = "localhost")
#Get Disk info
$colDisks = get-wmiobject Win32_LogicalDisk -computer $computer
$Now display it
" Device ID    Type               Size(M)     Free Space(M)"
ForEach ($Disk in $colDisks)
{
 $drivetype=$disk.drivetype
 Switch ($drivetype)
 {
     2 {$drivetype="FDD"}
     3 {$drivetype="HDD"}
     4 {$drivetype="Net"}
     5 {$drivetype="CD "}
 }
"    {0}         {1}       {2,15:n}  {3,15:n}" -f $Disk.DeviceID, $drivetype,
$($disk.Size/1mb), $($disk.freespace/1mb)
}
""
PSH [D:\foo]: .\get-disksize.ps1
Device ID    Type               Size(M)     Free Space(M)
   C:         HDD             20,928.43         1,005.85
   D:         HDD             21,202.97         2,783.07
   E:         HDD             53,168.21         2,460.73
   F:         CD               4,270.18             0.00
   L:         Net          1,526,214.19       502,263.14
   R:         Net            675,402.00       556,902.56
   S:         Net             76,253.84        34,930.72
   T:         Net                  0.00             0.00
   U:         Net                  0.00             0.00
   Y:         Net             69,970.60         8,091.59

A rich set of control structures is available to you while you're writing scripts, including:

If-then-else

You can test some condition (e.g., whether a user exists in AD) and based on that test, carry out operations (e.g., add the user) if the test succeeds, or do something else (e.g., issue an error message) if it does not. For details on the syntax of this construct, type Get-Help About_If.

Switch

This evaluates an item against a set of possible values and takes the action based on that evaluation. You could, for example, obtain the BIOS version of a system, and then test for each possible value. For details on the syntax of switch construct, type Get-Help About_Switch.

Looping

There are three looping control structures: For, Do-Until, and While. Typing Get-Help about_while provides more information on the While statement.

For and For-each

These iterate through an array or a set of values. Type Get-Help About_For and Get-Help About_ForEach for more information about the For statements.

Throw and Trap

These generate and catch errors.

Unfortunately there is very little documentation within PowerShell on Throw and Trap, as noted in http://blogs.msdn.com/powershell/archive/2006/12/29/documenting-trap-and-throw.aspx. See http://huddledmasses.org/trap-exception-in-powershell/ for more details about Throw and Trap.