Getting to know PowerShell
Exploring the more advanced Windows tools is a great way to begin taking control of your PC. Learn about Task Manager, for example, and you’ll soon be able to detect, and importantly, close down failing processes that might be slowing down your computer.
Relying on the standard applets presents all kinds of problems, though. You have to manually launch them every time you want to do something. Then you’re forced to work your way through the interface, perhaps choosing the same settings and options, over and over again. And even after all this, the applet might not do exactly what you need.
Fortunately, there is another way. PowerShell is a powerful scripting language that enables you to take full control of every aspect of your PC. Whether you need to watch running processes, monitor the file system, tweak the registry, download files, analyse web pages, create reports or do just about anything else on your local PC or any other networked system, PowerShell can help you get the job done, as precisely as you require, and as quickly as possible.
What’s more, while it can sometimes be complicated, you don’t have to be a programmer to begin learning a few scripting basics. In fact, if you work at the Windows command line, even occasionally you could be carrying out useful tasks in PowerShell with just a few minute’s study.
To launch PowerShell, type ‘powershell’ into the Search box, then right-click the Windows PowerShell entry and choose ‘Run as administrator’.
As you’ll see, the PowerShell interface looks and feels almost identical to the standard command line. And in many ways, this is a good thing, because it means you can use all the commands you know already.
Enter DIR to list the files in a folder, for instance, cls to clear the screen, or IPCONFIG to list your network adapters; everything works as you’d expect.
What you do get, though, is many new commands – or cmdlets (pronounced ‘command-lets’) in PowerShell-speak – and, fortunately, there’s a cmdlet to list them all. Type get-command and press [Enter] to take a look.
For now, ignore the functions and look only at the cmdlets. As you’ll see, cmdlets have a clear verb-noun naming structure: Start-Process, Clear-EventLog, Get- ComputerRestorePoint, Restart- Computer, and so on. This makes them quite easy to understand but, of course, you’ll often need more detail.
Enter Update-Help to download and install the documentation, then use the Get-Help cmdlet, like this, to find out a bit more about PowerShell:
The first line displays specific help on Start-Process; the second lists cmdlets with ‘service’ in the name; and the third just searches the help system for any items containing the word ‘clock’ – great when you know what you want to do, but just aren’t sure which cmdlet to use.
Enough of the theory; it’s time to do some real work. Let’s start by using PowerShell to collect some data on our system, like this: Get-Process.
As you’ll probably guess from the cmdlet name, this gets a list of processes currently running on your system (just the same as you would see in Task Manager), and displays their CPU and RAM use, along with some other statistics.
That’s already useful, and not something you can do easily in Windows alone, but we’re just getting started. Next, enter this:
Get-Process | Where-Object CPU -gt 5
As before, PowerShell is first checking your running processes. The pipeline character tells PowerShell to pass that list to the Where cmdlet. And this scans through the process list, looking for anything that matches the condition we’ve set – that it should have used greater than five seconds of CPU time (-gt is greater than; -ge is greater than or equal to; -lt is less than; -le is less than or equal to).
We’ve now filtered our original list a little, then, but there’s still more to do. The next step is to enter this:
Get-Process | Where-Object CPU -gt 5 | Sort-Object handles -descending
We’re still fetching your running processes and picking out the CPU hogs, but now PowerShell is also sorting the remaining processes by their number of handles (a measure of how many files, memory blocks and other objects a process has open).
Again, this is just an example, so tweak it; sort by CPU, say, or ProcessName (the column headers at the top of the Get-Process list will give you an idea of the names you can use).
As you can see, there are plenty of ways to customise and filter whatever PowerShell returns, but there’s a problem: we’re still only getting plain text results. So try this:
Get-Process | Where-Object CPU -gt 5 | Sort-Object handles -descending | Out-GridView
Now PowerShell doesn’t only filter and sort the list; it also displays the results in an interactive grid. You can hide, re-order or sort columns, and filter your data in various ways. And once you’re happy, any selected rows can be copied to the clipboard, ready for using anywhere else.
This isn’t bad for a single line of code and, of course, you can have as many lines as you need, but there’s more. Because PowerShell cmdlets work in such a consistent way, you can take this example and reuse it almost immediately. Take a look at these examples:
Get-Winevent System | Where-Object LevelDisplayName -eq "Critical" | Out-GridView
Get-Service | Where-Object status -eq "running" | Sort-Object displayname | Out-GridView
The first gets the contents of the Windows System log, looks for critical errors and displays them in a table. The second fetches our running services, again sorting them to suit our needs. And both examples can be further tweaked and customised in many different ways.
Take control with PowerShell
PowerShell provides plenty of sorting and filtering options, then, but it’s not just a passive reporting tool. Take a look at this:
Get-Service | Out-GridView -Title ‘Select service to restart!’ -OutputMode Single | Restart-Service -WhatIf
We’re getting a list of installed services, and displaying them with a custom window title as a user prompt. The -OutputMode Single switch tells PowerShell that we’re allowed to select one item in the list. If we do this, and click ‘OK’, our chosen service is passed along the pipeline to the next cmdlet, Start-Service, which stops and starts it for us, which is very useful as a way to try to revive any services that are misbehaving.
Or, at least, it would restart the service if we hadn’t included the -WhatIf switch, which tells PowerShell to simply display its action instead. This is a handy safety option, which means you can see how a cmdlet might work without the risk of, in this case, accidentally stopping a service that really should be left alone. But if you want to try it for real, enter the same cmdlet without the -WhatIf, and you’ll have created your very own custom service-restarting tool.
You can, of course, do something similar with processes, services, and any other objects PowerShell can manipulate. But even that’s not the end of the story:
Get-Service -ComputerName MyPC | Out-GridView -OutputMode Single | Restart-Service -WhatIf
Cmdlets like Get-Service and Get-Process aren’t restricted to your local system. Use the -ComputerName switch with the name of a network computer and you’re able to see what it’s running, too (assuming your Windows user account has the privileges to access them). PowerShell can then manage remote systems in exactly the same way as your own PC.
So far we’ve been working only in the PowerShell console, entering commands one by one and seeing the results right away. There is another way to run code, though – in the PowerShell Integrated Scripting Environment (ISE). It’s a little more complex, but much better when you’d like to string several cmdlets together, or create some code for reuse later. Launch it by searching for PowerShell and clicking ‘Windows PowerShell ISE’, entering Powershell-ISE.exe in the Run box, or by entering ISE at the PowerShell console.
The ISE opens with a two-pane interface. On the left is the console, where you can enter PowerShell commands. On the right is the Commands Add-On, a handy tool that can help you build commands with the mouse.
Type process in the Commands ‘Name’ box; you’ll see various matching cmdlets. Select ‘Get-Process’ to see its parameters, helping you understand what the cmdlet can do. Click the ‘Name’ tab, for instance, and you’ll find a Module box. What does this do? Check it and click ‘Run’. The Commands Add-On builds the cmdlet Get-Process -Module, runs it in the console, and displays the results – a list of all your processes, where each one includes its loaded modules (DLLs and other support files).
While this can be helpful, the ISE console also has some extra tricks to speed up your PowerShell coding. Begin typing a cmdlet (try Get-Process again) and ISE displays possible matches. By the time you’ve reached Get-Pro, the correct cmdlet should be highlighted, and you can press [Tab] to automatically enter the remaining characters.
It’s a similar story when it comes to entering parameters. Tap the space bar, then a hyphen, and ISE lists the various Get-Process options. Use the cursor keys to scroll down, then select ‘-Module’, press [Enter] and again it is automatically added to your command, no typing required.
As you can see, there’s more to learn in the ISE, but it does also make it easier to explore what PowerShell has to offer. Now we just have to use it to build a script.
Click ‘View > Show Script Pane’ to reveal the script pane. This is a separate area where you can enter a string of commands, across as many lines as necessary, without having them executed immediately. Instead, you can run all the commands in the Script pane at any time by pressing [F5] or clicking ‘Debug > Run’.
To give this a try, enter the following four commands into the Script pane.
$computername = read-host "Which computer name would you like to check?"
$os = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computername
$lastbootuptime = $os.ConvertToDateTime
Write-output "$computername last boot time was $lastbootuptime"
This is a simple script, which tries to find out the last boot time for whatever network computer you specify. Although very short, it’s much more advanced than our previous code, and introduces several new concepts.
The first line, for example, uses the read-host cmdlet to display a prompt, asking the user to enter a computer name. This is then stored in a variable called $computername.
The second line uses WMI to retrieve the operating system for the specified computer, while the third then obtains its boot time and converts it into a readable format. (Don’t worry about the technical details here; all you really need to remember is that Get-WmiObject can return useful information about your system configuration.)
Finally, the last Write-output cmdlet sends a message to the console. The variables will be replaced by their actual values so, for example, you might see "MyServer last boot time was 06/10/2014 08:30".
Press [F5] to launch the script. If you can access a networked PC, enter its name, otherwise enter localhost or just a period to check the local system. And that’s it – your first multi-line script. Click ‘File > Save As’ and save it as C:ScriptsLastBootTime.ps1 (creating the folder, if necessary), ready to be recalled whenever you like.
Our sample ISE script was very small, but the principles can be used to run whatever you like. Visit the Microsoft Scripting Centre – or search for PowerShell Scripts – to locate more examples, copy and paste them into the scripting pane, and press [F5].
There is still one issue remaining, though: how can you run the script outside of PowerShell? Double-clicking it seems an obvious solution, but try this and the file opens in Notepad; less than helpful.
You could relaunch PowerShell and enter C:ScriptsLastBootTime.ps1 at the command line, but that won’t work, either. You’ll just see a message complaining that "running scripts is disabled on this system". This is normal; the default security settings place strict limits on scripts to prevent their abuse by malware.
To get around this problem, you need to find out more about PowerShell’s execution policy. The following cmdlets will help:
The first line should tell you that your policy is set to ‘restricted’, blocking scripts. If so, entering the second line sets execution policy to ‘RemoteSigned’, instead. This means your own scripts will run immediately, but any scripts you download will need to be digitally signed by a trusted publisher.
Test the new policy by entering C:ScriptsLastBootTime.ps1 again, and this time your script should run. If it’s too much hassle to enter the full path each time, just add C:Scripts (or whatever folder you choose for your scripts) to your PATH environment variable (press [Win]+[X], click ‘System > Advanced System Settings > Environment Variables’, double-click ‘Path’ in ‘System Variables’, then add a semi-colon and the folder – ;CScripts – to the end of your path).
This isn’t quite the end of the story. The official PowerShell library has some useful details on executing scripts, and there’s a neat trick you can use to launch scripts from a shortcut but otherwise you now know how to test, write and run PowerShell code. It’s time now to begin some serious scripting.
PowerShell tips and tricks
If you need to reuse a PowerShell command, don’t waste time retyping it. Press [F7] to view your recent history, select a command, press [Enter] to run it, or the right arrow to place it on the command line. See http://tinyurl.com/qyovam2 for more editing shortcuts.
Adding comments to your PowerShell scripts will help others understand what they do (or act as a reminder for you). Type a # character and whatever you enter for the rest of that line will be treated as a plain text comment and not processed as code.
Access Control Panel
PowerShell can access Windows components, as well as files. Use Get-ControlPanelItem to get a list of Control Panel applets, and something like Show-ControlPanelItem *display* to launch one.
Record a PowerShell session
Reviewing what happened in a PowerShell session can help the learning process. Enter the cmdlet Start-Transcript and all your console activities (including any output) are saved to a text file in your Documents folder. Enter Stop-Transcript to stop recording.
Need to download a file from a script? This is the easy way (see http://tinyurl.com/pdpvhdo for something smarter):
$client = New-Object "System.Net.WebClient"
You don’t have time to monitor everything your scripts are doing? You could set them up to send you an email, instead. Check the Send-MailMessage cmdlet for a basic example, or Peter Morrisey’s blog for something more powerful.
If you’re not sure how to use a cmdlet, use the Get-Help -examples switch, such as Get-Help Invoke-WebRequest -examples, to learn more.
The Invoke-RestMethod cmdlet can access the RSS feed of any web source and manipulate it however you like. Here’s a quick way to view what’s happening in Microsoft’s PowerShell blog:
Invoke-RestMethod -Uri http://blogs.msdn.com/powershell/rss.aspx | Select-Object Title, Link | Out-GridView
To process text files, use Get-Content to read them, manipulate the content how you want and use Set-Content to save changes. Mistakes could result in lost data, though – only work with copies of files until you’re sure you know what you’re doing.
Run scripts automatically
If you become a PowerShell master, you could even set up Task Scheduler to run scripts automatically, whenever you like. Read up on the New-ScheduledTaskAction, New-ScheduledTaskTrigger and Register-ScheduledTask cmdlets, and see this blog post for an example.
Enter PowerShell commands faster
Don’t waste time typing long commands at the PowerShell console. Enter just a few characters (Get-Pr for Get-Process, say), keep pressing tab and any matches appear. Or use an alias, a shorter version of the same text; npssc works in exactly the same way as New-PSSessionConfigurationFile, for example.
Enter Get-Alias to see the aliases you can use right now, and Set-Alias to create your own.
Extend your skills
Point your browser at Microsoft’s Scripting Centre, and look out for interesting sample scripts. Copy and paste these into the ISE, press [F5] to try them out, then read the code and try to figure out how they work – it’s a great way to learn the language.