Read Windows Server 2008 R2 Unleashed Online
Authors: Noel Morimoto
again returns a second possible match and enables you to cycle through the list of results.
Like the cmd command prompt, PowerShell’s Tab key auto-completion can also auto-
complete with wildcards. The difference between Tab key auto-completion in cmd and
PowerShell is that PowerShell can auto-complete commands. For example, you can enter a
partial command name and press the Tab key, and PowerShell steps through a list of possi-
ble command matches.
PowerShell can also auto-complete parameter names associated with a particular
command. Simply enter a command and partial parameter name and press the Tab key,
and PowerShell cycles through the parameters for the command that has been specified.
This method also works for variables associated with a command. In addition, PowerShell
performs auto-completion for methods and properties of variables and objects.
Command Types
When a command is executed in PowerShell, the command interpreter looks at the
command name to figure out what task to perform. This process includes determining the
ptg
type of command and how to process that command. There are four types of PowerShell
commands: cmdlets, shell function commands, script commands, and native commands.
cmdlet
The first command type is a cmdlet (pronounced “command-let”), which is similar to the
built-in commands in other CLI-based shells. The difference is that cmdlets are imple-
mented by using .NET classes compiled into a dynamic link library (DLL) and loaded into
PowerShell at runtime. This difference means there’s no fixed class of built-in cmdlets;
anyone can use the PowerShell Software Developers Kit (SDK) to write a custom cmdlet,
thus extending PowerShell’s functionality.
A cmdlet is always named as a verb and noun pair separated by a “-” (hyphen). The verb
specifies the action the cmdlet performs, and the noun specifies the object being operated
on. An example of a cmdlet being executed is shown as follows:
PS C:\> Get-Process
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
425 5 1608 1736 90 3.09 428 csrss
79 4 1292 540 86 1.00 468 csrss
193 4 2540 6528 94 2.16 2316 csrss
66 3 1128 3736 34 0.06 3192 dwm
708
CHAPTER 21
Automating Tasks Using PowerShell Scripting
412 11 13636 20832 125 3.52 1408 explorer
...
While executing cmdlets in PowerShell, you should take a couple of considerations into
account. Overall, PowerShell was created such that it is both forgiving and easy when it
comes to syntax. In addition, PowerShell also always attempts to fill in the blanks for a
user. Examples of this are illustrated in the following items:
. Cmdlets are always structured in a nonplural verb-noun format.
. Parameters and arguments are positional: Get-Process winword.
. Many arguments can use wildcards: Get-Process w*.
. Partial parameter names are also allowed: Get-Process –P w*.
NOTE
When executed, a cmdlet only processes a single record at a time.
Functions
The next type of command is a function. These commands provide a way to assign a
ptg
name to a list of commands. Functions are similar to subroutines and procedures in other
programming languages. The main difference between a script and a function is that a
new instance of the shell is started for each shell script, and functions run in the current
instance of the same shell.
NOTE
Functions defined at the command line remain in effect only during the current PowerShell
session. They are also local in scope and don’t apply to new PowerShell sessions.
Although a function defined at the command line is a useful way to create a series of
commands dynamically in the PowerShell environment, these functions reside only in
memory and are erased when PowerShell is closed and restarted. Therefore, although creat-
ing complex functions dynamically is possible, writing these functions as script commands
might be more practical. An example of a shell function command is as follows:
PS C:\> function showFiles {Get-ChildItem}
PS C:\> showfiles
Directory: Microsoft.PowerShell.Core\FileSystem::C:\
Understanding the PowerShell Basics
709
Mode LastWriteTime Length Name
---- ------------- ------ ----
21
d---- 9/4/2007 10:36 PM inetpub
d---- 4/17/2007 11:02 PM PerfLogs
d-r-- 9/5/2007 12:19 AM Program Files
d-r-- 9/5/2007 11:01 PM Users
d---- 9/14/2007 11:42 PM Windows
-a--- 3/26/2007 8:43 PM 24 autoexec.bat
-ar-s 8/13/2007 11:57 PM 8192 BOOTSECT.BAK
-a--- 3/26/2007 8:43 PM 10 config.sys
Advanced Functions
Advanced functions are a new feature that was introduced in PowerShell v2.0. The basic
premise behind advanced functions is to enable administrators and developers access to
the same type of functionality as a compiled cmdlet, but directly through the PowerShell
scripting language. An example of an advanced function is as follows:
function SuperFunction {
<#
ptg
.SYNOPSIS
Superduper Advanced Function.
.DESCRIPTION
This is my Superduper Advanced Function.
.PARAMETER Message
Message to write.
#>
param(
[Parameter(Position=0, Mandatory=$True, ValueFromPipeline=$True)]
[String] $Message
)
Write-Host $Message
}
In the previous example, you will see that one of the major identifying aspects of an
advanced function is the use of the CmdletBinding attribute. Usage of this attribute in an
advanced function allows PowerShell to bind the parameters in the same manner that it
binds parameters in a compiled cmdlet. For the SuperFunction example, CmdletBinding is
used to define the $Message parameter with position 0, as mandatory, and is able to accept
values from the pipeline. For example, the following shows the SuperFunction being
executed, which then prompts for a message string. That message string is then written to
the console:
710
CHAPTER 21
Automating Tasks Using PowerShell Scripting
PS C:\Users\tyson> SuperFunction
cmdlet SuperFunction at command pipeline position 1
Supply values for the following parameters:
Message: yo!
yo!
Finally, advanced functions can also use all of the methods and properties of the PSCmdlet
class, for example:
. Usage of all the input processing methods (Begin, Process, and End)
. Usage of the ShouldProcess and ShouldContinue methods, which can be used to get
user feedback before performing an action
. Usage of the ThrowTerminatingError method, which can be used to generate error
records
. Usage of a various number of Write methods
Scripts
Scripts, the third command type, are PowerShell commands stored in a .ps1 file. The
ptg
main difference from functions is that scripts are stored on disk and can be accessed any
time, unlike functions that don’t persist across PowerShell sessions.
Scripts can be run in a PowerShell session or at the cmd command prompt. To run a script
in a PowerShell session, type the script name without the extension. The script name can
be followed by any parameters. The shell then executes the first .ps1 file matching the
typed name in any of the paths located in the PowerShell $ENV:PATH variable.
To run a PowerShell script from a cmd command prompt, first use the CD command to
change to the directory where the script is located. Then run the PowerShell executable
with the command parameter and specifying which script to be run, as shown here:
C:\Scripts>powershell -command .\myscript.ps1
If you don’t want to change to the script’s directory with the cd command, you can also
run it by using an absolute path, as shown in this example:
C:\>powershell -command C:\Scripts\myscript.ps1
An important detail about scripts in PowerShell concerns their default security restrictions.
By default, scripts are not enabled to run as a method of protection against malicious
scripts. You can control this policy with the Set-ExecutionPolicy cmdlet, which is
explained later in this chapter.
Native Commands
The last type of command, a native command, consists of external programs that the
operating system can run. Because a new process must be created to run native
commands, they are less efficient than other types of PowerShell commands. Native
Understanding the PowerShell Basics
711
commands also have their own parameters for processing commands, which are usually
different from PowerShell parameters.
21
.NET Framework Integration
Most shells operate in a text-based environment, which means you typically have to
manipulate the output for automation purposes. For example, if you need to pipe data
from one command to the next, the output from the first command usually must be refor-
matted to meet the second command’s requirements. Although this method has worked
for years, dealing with text-based data can be difficult and frustrating.
Often, a lot of work is necessary to transform text data into a usable format. Microsoft has
set out to change the standard with PowerShell, however. Instead of transporting data as
plain text, PowerShell retrieves data in the form of .NET Framework objects, which makes
it possible for commands (or cmdlets) to access object properties and methods directly.
This change has simplified shell use. Instead of modifying text data, you can just refer to
the required data by name. Similarly, instead of writing code to transform data into a
usable format, you can simply refer to objects and manipulate them as needed.
Reflection
Reflection is a feature in the .NET Framework that enables developers to examine objects
ptg
and retrieve their supported methods, properties, fields, and so on. Because PowerShell is
built on the .NET Framework, it provides this feature, too, with the Get-Member cmdlet.
This cmdlet analyzes an object or collection of objects you pass to it via the pipeline. For
example, the following command analyzes the objects returned from the Get-Process
cmdlet and displays their associated properties and methods:
PS C:\> get-process | get-member
Developers often refer to this process as “interrogating” an object. This method of accessing
and retrieving information about an object can be very useful in understanding its methods
and properties without referring to MSDN documentation or searching the Internet.
Extended Type System (ETS)
You might think that scripting in PowerShell is typeless because you rarely need to
specify the type for a variable. PowerShell is actually type driven, however, because it
interfaces with different types of objects from the less-than-perfect .NET to Windows
Management Instrumentation (WMI), Component Object Model (COM), ActiveX Data
Objects (ADO), Active Directory Service Interfaces (ADSI), Extensible Markup Language
(XML), and even custom objects. However, you don’t need to be concerned about object
types because PowerShell adapts to different object types and displays its interpretation of
an object for you.
In a sense, PowerShell tries to provide a common abstraction layer that makes all object
interaction consistent, despite the type. This abstraction layer is called the PSObject, a
common object used for all object access in PowerShell. It can encapsulate any base object
(.NET, custom, and so on), any instance members, and implicit or explicit access to
adapted and type-based extended members, depending on the type of base object.
712
CHAPTER 21
Automating Tasks Using PowerShell Scripting
Furthermore, it can state its type and add members dynamically. To do this, PowerShell
uses the Extended Type System (ETS), which provides an interface that allows PowerShell
cmdlet and script developers to manipulate and change objects as needed.
NOTE
When you use the Get-Member cmdlet, the information returned is from PSObject.
Sometimes PSObject blocks members, methods, and properties from the original
object. If you want to view the blocked information, use the BaseObject property with
the PSBase standard name. For example, you could use the $Procs.PSBase | get-
member command to view blocked information for the $Procs object collection.
Needless to say, this topic is fairly advanced, as PSBase is hidden from view. The only time
you should need to use it is when the PSObject doesn’t interpret an object correctly or
you’re digging around for hidden jewels in PowerShell.
Static Classes and Methods
Certain .NET Framework classes cannot be used to create new objects. For example, if
you try to create a System.Math typed object using the New-Object cmdlet, the following
error occurs:
ptg
PS C:\> New-Object System.Math