Over a million developers have joined DZone.

PowerShell in Action – An Excerpt

Get an intro to PowerShell's command concepts and terminology in this early chapter excerpt from PowerShell in Action, the third edition.

· DevOps Zone

The DevOps zone is brought to you in partnership with Sonatype Nexus. The Nexus suite helps scale your DevOps delivery with continuous component intelligence integrated into development tools, including Eclipse, IntelliJ, Jenkins, Bamboo, SonarQube and more. Schedule a demo today

The core PowerShell language is based on the very mature IEEE standard POSIX 1003.2 grammar for the Korn shell which has a long history as a successful basis for modern shells like bash and zsh. The language design team (Jim Truher and Bruce Payette) deviated from this standard where necessary to address the specific needs of an object-based shell and to make it easier to write sophisticated scripts.

PowerShell syntax is aligned with C#. The major value this brings is that PowerShell code can be migrated to C#, when necessary for performance improvements, and, more importantly, C# examples can be easily converted to PowerShell — the more examples you have in a language, the better off you are.

Command Concepts and Terminology

Much of the terminology used in PowerShell will be familiar if you’ve used other shells in the Linux or Windows world. But because PowerShell is a new kind of shell, there are a number of terms that are different and a few new terms to learn. In this section, we’ll go over the PowerShell-specific concepts and terminology for command types and command syntax.

Commands and cmdlets

Commands are the fundamental part of any shell language; they’re what you type to get things done. A simple command looks like this:

command –parameter1 –parameter2 argument1 argument2

All commands are broken down into the command name, the parameters specified to the command, and the arguments to those parameters. You can think of a parameter as the receiver of a piece of information and the argument as the information itself.

NOTE: The distinction between parameter and argument may seem a bit strange from a programmer’s perspective. But if you’re used to languages such as Python and Visual Basic that allow for keyword parameters, PowerShell parameters correspond to the keywords, and arguments correspond to the values.

The first element in the command is the name of the command to be executed. The PowerShell interpreter looks at this name and determines which command to run and also which kind of command to run. In PowerShell, there are a number of categories of commands: cmdlets, shell function commands, script commands, workflow commands, and native Windows commands. Following the command name come zero or more parameters and/or arguments. A parameter starts with a dash, followed by the name of the parameter. An argument, on the other hand, is the value that will be associated with, or bound to, a specific parameter. Let’s look at an example:

PS (1) > Write-Output -InputObject Hello


In this example, the command is Write-Output, the parameter is -InputObject, and the argument is Hello.

What about the positional parameters? When a PowerShell command is created, the author of that command specifies information that allows PowerShell to determine which parameter to bind an argument to, even if the parameter name itself is missing. For example, the Write-Output command has been defined so that the first parameter is -InputObject. This lets you write

PS (2) > Write-Output Hello


The piece of the PowerShell interpreter that figures all of this out is called the parameter binder. The parameter binder is smart—it doesn’t require that you specify the full name of a parameter as long as you specify enough for it to uniquely distinguish what you mean.

NOTE: PowerShell isn’t case sensitive but we’ll tend to use the correct casing on commands and parameters to aid reading. It’s also a good practice when scripting as it’s easier to understand the code when you revisit it many months later.

What else does the parameter binder do? It’s in charge of determining how to match the types of arguments to the types of parameters. Remember that PowerShell is an object-based shell. Everything in PowerShell has a type. PowerShell uses a fairly complex type-conversion system to correctly put things together. When you type a command at the command line, you’re really typing strings. What happens if the command requires a different type of object? The parameter binder uses the type converter to try to convert that string into the correct type for the parameter. If you use a value that can’t be converted to the correct type you get an error message explaining that the type conversion failed. We’ll discuss this in more detail in chapter 2 when we talk about types.

What happens if the argument you want to pass to the command starts with a dash? This is where the quotes come in. Let’s use Write-Output to print out the string “-InputObject”:

PS (1) > Write-Output -InputObject "-InputObject"


And it works as desired. Alternatively, you could type this:

PS (2) > Write-Output "-InputObject"


The quotes keep the parameter binder from treating the quoted string as a parameter.

Another, less frequently used way of doing this is by using the special “end-of-parameters parameter, which is two hyphens back to back. Everything after this sequence will be treated as an argument, even if it looks like a parameter. For example, using -- you can also write out the string -InputObjects without using quotes:

PS (3) > Write-Output -- -InputObject


This is a convention standardized in the POSIX Shell and Utilities specification.

The final element of the basic command pattern is the switchparameter. These are parameters that don’t require an argument. They’re usually either present or absent (so obviously they can’t be positional). A good example of this is the -Recurse parameter on the dir command. This switch tells thedir command to display files from a specified directory as well as all its subdirectories:

PS (1) > dir -Recurse -Filter c*d.exe c:\windows

        Directory: C:\windows\system32



Mode                LastWriteTime     Length Name

----                -------------     ------ ----

-a---        29/10/2014     00:37     141824 CloudStorageWizard.exe

-a---        29/10/2014     01:28     357376 cmd.exe


As you can see, the -Recurse switch takes no arguments.

NOT: Athough it’s almost always the case that switch parameters don’t take arguments, it’s possible to specify arguments to them. We’ll save discussion of when and why you might do this for chapter 7 which focuses on scripts (shell functions and scripts are the only time you need this particular feature, so we’ll keep you in suspense for the time being).

Now that we’ve covered the basic anatomy of the command line, let’s go over the types of commands that PowerShell supports.

Command Categories

As we mentioned earlier, there are four categories of commands in PowerShell: cmdlets, functions, scripts, and native Win32 executables.


The first category of command is a cmdlet (pronounced “command-let”). Cmdlet is a term that’s specific to the PowerShell environment. A cmdlet is implemented by a .NET class that derives from the Cmdlet base class in the PowerShell Software Developers Kit (SDK).

NOT: Building cmdlets is a developer task and requires the PowerShell SDK. This SDK is freely available for download from Microsoft and includes extensive documentation along with many code samples. Our goal is to coach you to effectively use and script in the PowerShell environment, so we’re not going to do much more than mention the SDK in this book.

This category of command is compiled into a dynamic link library (DLL) and then loaded into the PowerShell process, usually when the shell starts up. Because the compiled code is loaded into the process, it’s the most efficient category of command to execute.

Cmdlets always have names of the form Verb-Noun, where the verb specifies the action and the noun specifies the object on which to operate. In traditional shells, cmdlets correspond most closely to what’s usually called a built-in command. In PowerShell, though, anybody can add a cmdlet to the runtime, so there isn’t any special class of built-in commands.


The next type of command is a function. This is a named piece of PowerShell script code that lives in memory while the interpreter is running and is discarded on exit. Functions consist of user-defined code that’s parsed once when defined. This parsed representation is preserved so it doesn’t have to be reparsed every time it’s used.

Functions in PowerShell version 1 could have named parameters like cmdlets but were otherwise fairly limited. In version 2, and later, this was fixed, and scripts and functions now have the full parameter specification capabilities of cmdlets. The same basic structure is followed for both types of commands. Functions and cmdlets have the same streaming behavior.

PowerShell workflows were introduced in PowerShell 3.0. Their syntax is similar to that of a function. When the workflow is first loaded in memory a PowerShell function is created that can be viewed through the function: PowerShell drive.


A script command is a piece of PowerShell code that lives in a text file with a .ps1 extension. These script files are loaded and parsed every time they’re run, making them somewhat slower than functions to start (although once started, they run at the same speed). In terms of parameter capabilities, shell function commands and script commands are identical.

Native Commands (Applications)

The last type of command is called a native command. These are external programs (typically executables) that can be executed by the operating system. Because running a native command involves creating a whole new process for the command, native commands are the slowest of the command types. Also, native commands do their own parameter processing and so don’t necessarily match the syntax of the other types of commands.

Native commands cover anything that can be run on a Windows computer, so you get a wide variety of behaviors. One of the biggest issues is when PowerShell waits for a command to finish but it just keeps on going. For example, say you’re starting a text document at the command line:

PS (1) > .\foo.txt

PS (2) >

You get the prompt back more or less immediately, and your default text editor will pop up (probably notepad.exe because that’s the default). The program to launch is determined by the file associations that are defined as part of the Windows -environment.

NOT: In PowerShell, unlike in cmd.exe, you have to prefix a command with or  if you want to run it out of the current directory. This is part of PowerShell’s “Secure by Design” philosophy. This particular security feature was adopted to prevent Trojan horse attacks where the user is lured into a directory and then told to run an innocuous command such as notepad.exe. Instead of running the system notepad.exe, they end up running a hostile program that the attacker has placed in that directory and named notepad.exe.

What about when you specify the editor explicitly?

PS (2) > notepad foo.txt

PS (3) >

The same thing happens—the command returns immediately. But what about when you run the command in the middle of a pipeline?

PS (3) > notepad foo.txt | sort-object

<exit notepad>

PS (4) >

Now PowerShell waits for the command to exit before giving you back the prompt. This can be handy when you want to insert something such as a graphical form editor in the middle of a script to do some processing. This is also the easiest way to make PowerShell wait for a process to exit. As you can see, the behavior of native commands depends on the type of native command, as well as where it appears in the pipeline.

A useful thing to remember is that the PowerShell interpreter itself is a native command: powershell.exe. This means you can call PowerShell from within PowerShell. When you do this, a second PowerShell process is created. In practice there’s nothing unusual about this—that’s basically how all shells work. PowerShell just doesn’t have to do it very often, making it much faster than conventional shell languages.

The ability to run a child PowerShell process is particularly useful if you want to have isolation in portions of your script. A separate process means that the child script can’t impact the caller’s environment. This feature is useful enough that PowerShell has special handling for this case, allowing you to embed the script to run inline. If you want to run a fragment of script in a child process, you can do so by passing the block of script to the child process delimited by braces. Here’s an example:

PS {1) > powershell { Get-Process *ss } | Format-Table name, handles


Name                                                Handles

----                                                -------

csrss                                                  1077

lsass                                                  1272

smss                                                     28


There are two things to note in this example. The script code in the braces can be any PowerShell code, and it will be passed through to the new PowerShell process. The special handling takes care of encoding the script in such a way that it’s passed properly to the child process. The other thing to note is that, when PowerShell is executed this way, the output of the process is serialized objects--the basic structure of the output is preserved—and so can be passed into other commands.

Desired State Configuration

Desired State Configuration (DSC) is a management platform in Windows PowerShell. It enables the deployment and management of configuration data for software services and the environment on which these services run. A configuration is created using PowerShell like syntax. The configuration is used to create a MOF (Managed Object Format) file which is passed to the remote machine on which the configuration will be applied.

The DevOps zone is brought to you in partnership with Sonatype Nexus. Use the Nexus Suite to automate your software supply chain and ensure you're using the highest quality open source components at every step of the development lifecycle. Get Nexus today


The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}