Wednesday, 5 April 2017

Master the PowerShell

Master the PowerShell

Discover how to get started with Microsoft’s powerful scripting tool, with Nick Peers

At first glance, the Windows PowerShell looks to be a facsimile of the Command Prompt, but to dismiss it as such leaves you missing a huge trick. In fact, PowerShell is a platform designed to automate many Windows tasks through a clever scripting language. It’s based on the .NET Framework, which gives it lots of flexibility and scope, particularly when you access it through the PowerShell ISE (Integrated Scripting Environment) program, which provides even more useful tools and shortcuts — such as syntax highlighting and IntelliSense tab completion — to help you build the perfect script to achieve what you want.


If you’ve already dabbled with the Command Prompt — and .bat batch files in particular — you’re already well on the road to getting to grips with PowerShell. Many familiar commands work in PowerShell, too — thanks to a clever aliasing system, you can type a Command Prompt command and it’s automatically translated into the correct PowerShell command.

In this article, we’re going to introduce you to the PowerShell from the perspective of someone who’s not encountered it before, and is interested in discovering what it may or may not be able to do for them. We’ll make some fairly basic assumptions — you’re aware of how programing and scripting work, for example — but we will start at the beginning, teaching you the fundamental building blocks of PowerShell. In the process, we’ll reveal what “cmdlets” are and how they work, plus you’ll discover how to stitch them together to form fully functional commands, gently easing you into the world of scripting. We’ll also introduce the basic syntax and structure of the language, while providing you with some real-world examples to try.

You’ll find out how to install the latest version of PowerShell in older versions of Windows, discover how to get help, and find some of the best online reference guides. You’ll also learn about setting up profiles, and gain useful tips and tricks to help you start to use PowerShell to make your own computing life that bit more easy. Ready to start on the road to becoming a PowerShell guru? Let’s go!

We’ll begin by opening PowerShell — if you’re running Windows 7, 8, or 8.1, check 'Get PowerShell' below to obtain the latest version. Click the “Start” button, and scroll down the “All Apps” list until you locate the “Windows PowerShell” folder. Click this to reveal two (or four if you’re running 64-bit Windows) options: “PowerShell” and “PowerShell ISE.” Let’s start with the basic PowerShell command prompt, so select “PowerShell.” This launches the application with non-administrative privileges, and places you in your own personal user folder, just like the Command Prompt. Right-click the shortcut, and choose “Run as Administrator,” and it places you at C:\Windows\System32. It goes without saying, though, that you shouldn’t run PowerShell as an administrator unless you specifically need to. For the purposes of this tutorial, we’re going to stick to running it as a regular user, except where stated.

The PowerShell window opens, providing you with a similar — at first glance — interface to the regular Command Prompt. You can customize the view by right-clicking its menu bar and choosing “Properties” to reveal a tabbed window. The options are broadly identical to the Command Prompt — use the “Font,” “Layout,” and “Colors” tabs to customize its look and feel.

To help you plot a route through potentially maze-like commands, the text changes color as you type different parts of the command: cmdlets and aliases are yellow, with parameters displayed in white, and flags (switches preceded by the – (dash) symbol) in gray. Variables are displayed in green, and text strings in dark blue.

As an aside, you can change these — and other message colors — if you don’t like them, but those options are edited using PowerShell commands. We’ll look at them in more detail later on.

FIRST STEPS


PowerShell is about building blocks. Those blocks are known as “cmdlets.” They’re called this to differentiate them from commands as used by the Command Prompt. In the Command Prompt, commands either refer to specific programs, such as chkdsk.exe or edit.com, or are “internal commands” related to the main command.com program (for example, “dir” and “mkdir”).

Cmdlets work in a different way. PowerShell works through the .NET Framework, so cmdlets are actually instances of .NET Framework classes, not standalone executable files. What this means in practice is that cmdlets rely on PowerShell to handle the parsing of commands, plus provide any error presentation and output formatting.

Furthermore, while commands are designed to work on their own, cmdlets can work in isolation, or be used in combination with others to create more featurecomplete commands. Cmdlets can be split into various types, enabling you to mix and match with precision to get the results you need. Indeed, with some practice, you’ll be able to build complete applications from just a few dozen lines of code.

CMDLETS UNCOVERED


All cmdlets follow the same structure: verb-noun. So you have “Get-Alias,” “Clear-Histor y,” “Set-Location,” and so on, which helps make them easier to grasp. The verb part of the cmdlet reveals what it’s designed to do — for example, “Get” cmdlets are designed to retrieve data, while “Set” cmdlets are used to establish or change data. “Format” cmdlets format data in a particular way, and “Out” cmdlets are designed to direct your command’s output to a specific destination, whether that’s the screen, a file, or somewhere else.

Many cmdlets have abbreviated aliases, too. These are shortened forms of the cmdlet — for example, “clhy” refers to “Clear-History,” the command for deleting all entries from the command history. Others link back to the Command Prompt, to make it easier for those with experience of the command line to migrate across to PowerShell. For example, “cd” refers to “Set-Location,” which is used to change the working directory in PowerShell, while “dir” is the alias for “Get-ChildItem,” which is used to list the files and folders in the current directory. To list all aliases, use the “Get-Alias” cmdlet on its own, like so:

> Get-Alias

Add “alias” to the end, substituting “alias” with your chosen alias, to get a specific command. For example:

> Get-Alias dir

To find out more about what specific cmdlets and aliases can do — and see examples of them in action — use PowerShell’s help commands. The box 'Get help' reveals what you need to know.

You can also create your own aliases using the “function” cmdlet — we touch on this in the profiles box 'Build a profile'.

USING PARAMETERS


Just like regular Command Prompt commands, cmdlets are controlled using various parameters (also referred to as switches and flags). The 'Get help' box reveals how to identify what a cmdlet’s parameters are, and what they do, plus see some examples.

PowerShell also supports variables, which should be preceded with a $ string. Each variable is defined on its own line, and then that variable can be called later on. For example, try the following lines:

> $Bill = 100
> $TAX = 20
> $Total = $Bill + $TAX
> “Your final bill is” +$Total

As an aside, you could write “Your final bill is $Total” and that would work, too, because PowerShell is smart enough to recognize that $Total is variable. On other hand, if you wanted to write $Total as a word and not the variable, use ‘Your final bill is $Total’ instead. (More on command syntax in a minute.) You’ll come across a special variable ($_) that may or may not precede something else, such as “$_.status.” This is a placeholder, and we’ll look at it later.

MORE COMMAND SYNTAX


PowerShell uses standard scripting operators to help build commands — everything from commas to separate items in a list, to enclosing text strings in double quotation marks (as you saw earlier, PowerShell is smart enough to identify variables inside quote marks). There are also some handy conditional operators you can use when creating conditional statements. Use “-eq” to mean equals, and “-ne” to mean not equal. Enter “-gt” for greater than (and “-ge” for greater than or equal), or “-lt” and “-le” for less than or less than or equal.

The pipe symbol — “|” — combines two or more commands in a single line of code. It’s used to “pipe” the output of one command so it becomes the input of the next command. If you type “ping google.com” you’ll see a list of text describing the results — now type the following command:

> Ping google.com | Select-String packets | Out-File tempfile.txt

This pings google.com as before, but this time it searches the output for lines containing “packet,” then saves them into a tempfile.txt file, which it saves to the current working directory. Open File Explorer to locate the file — it contains a single line of text, something like “Packets: Sent = 4, Received = 4, Lost = 0 (0% loss).”

CONDITIONAL STATEMENTS


Sometimes you want your commands to process differently depending on whether or not specific conditions are met. Like all good scripting and programing languages, PowerShell supports this through “If” and “Else” statements (as well as variants, such as “ForEach”). The basic structure for conditional commands is this:

> If (condition) {perform task if condition is met or true}

You’ll see two different types of bracket have been referenced here. Use parentheses (regular brackets) for required options within the loop. Your conditions can include “-And,” “-Not,” and “-Or” flags to provide more complex conditions. For example, the following performs the task if either test1 or test2 conditions are met:

> If (test1 -Or test2) {perform task}

Replace “-Or” with “-And,” and both test conditions would be required; change it to “-Not,” and test1 would need to be met and test2 specifically not met for the task to run.

Curly braces — {} — can also be used for block expressions within a command that explicitly looks for a condition to be met. For example, the “Where-Object” cmdlet allows you to filter data returned by other cmdlets, as the following example demonstrates:

> Get-Service | Where-Object {$_.status -eq “stopped”}

This produces a list of services on your PC that aren’t currently running. The “$_” placeholder enables you to capture the output of “Get-Service” without having to run the command again. The “status” portion of the variable is a specific child property linked to “Get-Service.” You can find out what these are using the “Get-
Member” command, like so:

> Get-Service | Get-Member

Last, but not least, you can also use square brackets — [] — which represent optional elements that aren’t required for a cmdlet to run. For example:

> Get-Service [w]*

This produces a filtered list of services that begin with the letter “w.” Square brackets are also used for certain math functions.

PUT IT ALL TOGETHER


You can combine cmdlets, variables, parameters, and syntax to perform quite complex tasks with what amounts to not very much code. The following example provides a complete list of aliases, their associated cmdlets, and available parameters, sorted by cmdlet name rather than alias. Look closely, and you should see some logic — the “sort” command clearly refers to “ResolvedCommand” (the cmdlet name), for example, while the “Get-Help” cmdlet pulls the information about each cmdlet’s parameters. Finally, the “Format-Table” cmdlet is used to output the results neatly over three columns.

> Get-Alias | select Name, ResolvedCommand, @{Name=”Description”; Exp={ Get-Help $_ | Select -ExpandProperty Synopsis }} | sort ResolvedCommand | Format-Table -Wrap

Before we move on, having to type these commands in full can be time-consuming, but here’s a handy shortcut: start typing a cmdlet, then press Tab to auto-complete it — if more than one match is found, keep hitting Tab until your cmdlet is displayed, and press Shift-Tab to cycle back through the list in case you miss your target.

HANDY CMDLETS


Let’s introduce some more cmdlets. An exhaustive A-Z list is beyond us, so bookmark the “Task-Based Guide to Windows PowerShell Cmdlets” at https://technet.microsoft.com/en-us/library/dd772285.aspx. It’s organized into tasks under such groups as “Dates and Times,” “Files and Folders,” “Help and Information,” “Scripting Techniques,” and “System Administration Tasks.”

First up, the “Get-Date” cmdlet lists the date and time — use the “-displayhint” parameter, and specify either date or time to filter the output. You can also use “Get-Date” to specify a variable using date/time format, and to perform various forms of time- or date-based arithmetic, using such parameters as “AddSeconds” through to “AddYears.” The following is a handy way to quickly calculate time offsets for different parts of the world:

> (Get-Date).AddHours(-5)

Next, use “Copy-Item” to copy files or folders to a new location — you need to specify the source, then the destination. Use the wildcard (*) character to copy all files in a folder to the location, or “*.doc” to restrict it to copying only specific file types:

> Copy-Item c:\users\nickd\documents\scripts\*.ps1 c:\users\nickd\downloads\test\

Related file-based cmdlets include “Remove-Item” (delete), “Move-Item,” “Rename-Item,” and “New-Item” (create a file or folder — use the “-type” parameter to specify “file” or “directory’ respectively).

We’ve touched on using “Out-File” to record a command’s output to a text file, but what if you want to append a string of text to an existing file, instead of creating one? The “Add-Content” cmdlet does just that. By default, it appends your string immediately after the last character in the file, but it’s likely you’ll want to append it to a new line, so precede your text with “`n,” like so:

> Add-Content c:\users\nickd\documents\text.txt “`nThe End”

Want to output your command to a web page? Use the “ConvertTo-Html” cmdlet in a piped command, in conjunction with a “Get-” command and “Set-Content” (which does the actual writing of data):

> Get-Process | ConvertTo-Html | Set-Content c:\user\nickd\downloads\test.htm

PowerShell can be used to manipulate services (and processes), using a number of different cmdlets. Available commands — all self-explanatory, and requiring you to run PowerShell as an administrator — include “Start-Service,” “Stop-Service,” “Restart-Service,” “Suspend-Service,” and “Resume-Service.” These need to be followed by the service’s name as stored in the Registry — if you don’t know this, use the “-displayname” parameter, in conjunction with the name of the service, as it appears under services.msc:

> Restart-Service -displayname “File History Service”

Note, you may see an error message appear if you attempt to pause the vast majority of services that don’t support being paused and resumed. That’s normal, and like all PowerShell error messages, there’s usually enough information provided to help you grasp what’s going on.

BUILD A COMMAND


We have touched on how cmdlets work best when used in conjunction with others to form complete commands. Here’s a practical example of how to use PowerShell to change the message colors it displays, with the help of the “Get-Host” cmdlet. Start by typing the following, to see how PowerShell currently displays warning messages:

> Write-Warning “Alert!”

You’ll see the message is displayed as yellow text on a black background, which is fine, unless you’ve modified the background and font colors, as outlined earlier. So how do you go about changing it? Easy. We use the “Get-Host” cmdlet to extract the current properties of the command window using its “PrivateData” property (which is anything but private — oh the irony):

> $a = (Get-Host).PrivateData
> echo $a

This reveals no fewer than 10 child properties for “PrivateData,” including two referring to warning colors. We can then change these, like so:

> $a.WarningBackgroundColor = “red”
> $a.WarningForegroundColor = “white”

Now try the “Write-Warning” cmdlet again. Note, however, that the changes won’t survive the current PowerShell session —  close the window and open it again, and you’re back to the original settings. This leads us on to the concept of PowerShell profiles, which you can find out more about in 'Build a profile'.

BUILDING SCRIPTS


Scripting is a way of storing and running multiple commands from a single file. Command Prompt scripts are written as plain text files, and saved using the .bat extension. Each command is placed on a separate line, and they’re run in sequence when the batch file is called from the Command Prompt by navigating to the directory the script is stored in, typing its name — ”script.bat,” for example — and hitting Enter.

PowerShell supports scripts, too — again, these are text files, but they’re stored using the .ps1 file extension. They’re then called from the PowerShell command prompt — if your script resides in the same directory you’re currently in, use the following:

> .\filename.ps1

If you need to call it from another directory, use the following syntax:

> & “c:\users\nickd\script.ps1”

The first time you attempt this, you’ll receive an error message telling you that scripts can’t be run. This is down to PowerShell’s security policy, which is set to “Restricted” by default. You can change this policy within PowerShell, but you need to exit and relaunch it as an administrator to do so. Once done, type the following:

> Set-ExecutionPolicy -ExecutionPolicyRemoteSigned

Press Y, and hit Enter when prompted, and try running your script again. This time, it should work — ”RemoteSigned” basically allows all local scripts, as well as downloaded scripts that have been signed by a trusted publisher, to run.

While you can create scripts by hand in a text editor, Windows provides all the tools you need to build and test .ps1 scripts in PowerShell ISE, which provides a more fully rounded experience, and is geared toward making it easier and quicker to write, test, and run scripts. Check out the 'PowerShell ISE' for an overview of how it works.

You’ve now started on your journey to tapping into scripting using PowerShell and PowerShell ISE. We’ve barely scratched the surface, but you should have enough of a grounding to strike out on your own. To help you move on to the next level, visit https://gallery.technet.microsoft.com/ScriptCenter, where you’ll find thousands of script resources for PowerShell. They’ve technically been written for IT professionals, but you’ll find plenty of examples that you can make use of as a regular user, too — for example, the “Reset Windows Update Agent” script enables you to attempt to fix problems with Windows Update from the PowerShell interface.

Before we go, one final use for PowerShell (run as an administrator) is to remove Windows Store apps from your PC. Use the following syntax:

> Get-AppxPackage *appname* | Remove-AppxPackage

Substitute “appname” with the name of the app you wish to remove, and they’re all up for grabs, even built-in apps ignored by Apps & Features. To get a full list, use:

> Get-AppxPackage -Alluser | FormatList-Property PackageFullname


Get PowerShell


We’re featuring the most recent release of PowerShell — version 5.1 — and it comes preinstalled with the latest version of Windows 10. All you need to do is launch it, either from the Start menu’s “All Apps” list, or by typing “powershell” into the “Search” box. You can then right-click its Taskbar icon and choose “Pin to Taskbar” for a convenient shortcut going forward.

Windows 8 and 8.1 users currently use PowerShell 4. If you want to upgrade to version 5.1, simply download the correct version — x86 (32-bit) or x64 (64-bit) — from https://msdn.microsoft.com/enus/powershell/wmf/5.1/install-configure. Doubleclick it, and follow the installation prompts.

Windows 7 ships with an even older version of PowerShell, dating back to 2009. To upgrade that, you first need to verify the .NET Framework 4.5.2 is installed (a link to it is provided at the site above, or you can install it through Windows Update). Once done, download the relevant x86 or x64 standalone installer file (around 65MB), then double-click it, and again follow the prompts.

Once installed, you’re prompted to reboot, so do so, and impatiently wait for Windows to reload. Then it’s a case of simply opening PowerShell in the usual way — via the “Start” menu or by pressing Win-Q in Windows 8 to open the Search charm. The latest version powers up (you can verify this by checking out the copyright notice, which should now read “2016,” rather than “2009” or “2012”), and you’re ready to delve into PowerShell without missing out on all the latest improvements and new features.

To see what’s new, click “New Scenarios and Features” on the download page for version 5.1, and also check out the “WMF 5.0” link, where you’ll discover major features introduced since Windows 7 and 8 were released.


Get help


There’s plenty of help — offline and online — waiting for you with PowerShell. The obvious place to start is with its own built-in help tools. Type the following:

> help cmdlet

Replace “cmdlet” with your cmdlet’s or alias’s name. You’ll receive a prompt that the more detailed help files require installing, but to avoid a string of error messages, first close and restart PowerShell as an administrator, then type:

> Update-Help

A green progress bar appears, and then the files are added, one module at a time — don’t be surprised to end with an error message or two, which can be safely ignored. Close and restart PowerShell again.

Now the help files have been replaced, use the following command:

> Get-Help cmdlet

You can add some handy parameters: “-detailed” (“Get-Help cmdlet -detailed”) provides a list of all available parameters for that cmdlet, plus examples of them in action. Use “-examples” if you only want to view examples. One downside of the help file is that you need to keep scrolling back to reference it; add “-online” and it opens in your browser, enabling you to view it side-by-side while coding.

You’ll also find lots of websites providing you with more help and advice, too. One of our favorites can be found at www.computerperformance.co.uk/powershell/ — although written for an older version of PowerShell, its basic advice holds true, and it provides a good reference guide, with a handy, if labyrinthine, navigation panel. There’s a useful A-Z reference of cmdlets at https://ss64.com/ps/, and don’t forget to check Microsoft’s Developer Network at https://msdn.microsoft.com/en-us/powershell for lots more resources — go to “Documentation > Windows PowerShell” for a detailed introduction.


Build a profile


By default, everything you set up in PowerShell — variables, functions, and other customizations, such as the color of warning messages — is lost when you close the current session. If you’d like to preserve this across multiple sessions, you need to create a profile. First, display the path to the Windows PowerShell profile by typing:

> $profile
> test-path $profile

This reveals that the profile will reside in your Documents folder, while the second command returns a value of “False,” indicating that the profile doesn’t yet exist. To create a profile, type:

> new-item -path $profile -itemtype file -force

Type the following to open it in Notepad:

> notepad $profile

A blank document is opened, ready for you to record your variables and other customizations. For example, to change the warning message as outlined in the main text, add the following three lines of code:

$a = (Get-Host).PrivateData
$a.WarningBackgroundColor = “red”
$a.WarningForegroundColor = “white”

Add the following line, and you can edit your profile simply by issuing the command “pro” into PowerShell going forward:

function pro {notepad $profile}

Save the file in Notepad, then close and reopen PowerShell — your customizations should be in place. It basically works like a script file, but is loaded each time you launch PowerShell. It only affects PowerShell when you run it as the current user — if you want to create a profile that affects all users and shells, simply launch PowerShell as an administrator instead. The profile is stored inside the Windows\System32 folder, and applies to all users of your PC.


PowerShell ISE


Once you’ve got to grips with the basics, we recommend switching to coding, and developing scripts using PowerShell ISE (search for “ISE” in the Windows search box). It opens to a multi-pane window: the console window appears to mimic the basic PowerShell interface, but comes with some hidden extras. First, you can input and edit multiple lines of code at once — hit Shift-Enter to add an extra line.

Second, as you start typing cmdlets, the Snippets feature automatically suggests commands to enter (select them with the arrow keys, then a list of supported parameters for the selected cmdlet is displayed; press Tab to insert the cmdlet). Right-click the console window, and choose “IntelliSense” for an even more helpful tool that suggests parameters, parameter values, and even files and folders.

You’ll see a functional menu bar with lots of options related to scripting, and the elusive script window can be brought into view by pressing Ctrl-R. Snippets and IntelliSense work inside here, too, and you can run all your script by pressing F5, plus save it to disk for future use. You can also run just a small portion of it — select the code in question, then hit F5 to run it in isolation from the rest of your script.

The Command panel on the right offers an alternative, interactive way of inserting cmdlets. Select one from the list for a description, then click “Insert” to insert it into your console, or click the “Show Details” to view all available parameters. Select one or add in any required information, then click “Insert” to insert a fully formed command into the console.

Finally, you can expand ISE’s capabilities by choosing “Add-Ons > Open Add-Ons Website” to browse community-written snippets that add different types of functionality to ISE.