PowerShell

Important: take note of PowerShell is open sourced and is available on Linux | Blog | Microsoft Azure which is exciting news! This means we will soon be able to use PowerShell on Windows, Linux and Mac. Although we can use Bash on all three platforms too! As of January 2018 PowerShell Core is available on all three platforms and has been released, see PowerShell Core 6.0: Generally Available (GA) and Supported! | PowerShell Team Blog for details.

Introduction

Possibly the best place to start from when new to PowerShell is PowerShell Documentation | Microsoft Docs, closely followed by Scripting with Windows PowerShell on Microsoft's website, which is a great launchpad for getting an introduction to PowerShell as well as digging deeper. There is some background information on PowerShell at Windows PowerShell - Wikipedia, the free encyclopedia which I have also found helpful.

It is important to note that "PowerShell Core" is the cross platform version of PowerShell and it is built on .NET core, you can get it from PowerShell/PowerShell: PowerShell for every system! and it can be installed on Windows alongside regular PowerShell, which is technically called "Windows PowerShell". The difference between Windows PowerShell and PowerShell Core is explained at PowerShell 6.0 Roadmap: CoreCLR, Backwards Compatibility, and More! | PowerShell Team Blog. In addition Getting Started with PowerShell Core on Windows, Mac, and Linux | PowerShell Team Blog is a great article to help you get started with PowerShell Core.

When installing PowerShell on a Mac I would recommend using the Homebrew-Cask command:
brew cask install powershell which is fully explained at Installing PowerShell Core on macOS | Microsoft Docs. Following a new release you will need to perform and upgrade as follows:
brew update
brew cask upgrade powershell

This will get you to the latest PowerShell Core on your Mac.

It is also worth noting that PowerShell has "Language Modes" where PowerShell can be placed into a restrictive mode for security reasons. This is to do with the security of the device PowerShell is running on and is designed to help prevent malicious attacks. See about_Language_Modes | Microsoft Docs.

Versions

If you want to know which version of PowerShell you are running then open an interactive PowerShell and type $PSVersionTable you can see from the list "PSVersion" which tells you which version you have and also "PSCompatibleVersions" which tells you which versions of PowerShell you have compatibility with.

If $PSVersionTable.PSEdition returns a null then it is an old version of PowerShell Windows, otherwise it will return "Core" or "Desktop" where Core means PowerShell Core and Desktop means full PowerShell Windows.

I have however noted that whilst my Windows 7 laptop and Windows Server 2012 R2 VM have the same PowerShell versions and "compatible versions" the available cmdlets are different. For example a lot of useful networking and IP related cmdlets like Get-NetIPAddress are only in Windows 8 or Server 2012 and above.

Legacy

Should you happen to need PowerShell 2.0 for Windows XP then use the following link: Download Update for Windows XP (KB968930) from Official Microsoft Download Center, however I strongly recommend you stop using Windows XP as it stopped getting security updates in April 2014 and so is not safe to use. However there are variants of Windows XP in the embedded and retail space which are still being supported but not for long.

Documentation

The best place to start is PowerShell Documentation | Microsoft Docs, from where you will find everything you need. Another good starting point is Windows PowerShell Core About Topics which is almost a language reference. There is also Windows PowerShell User's Guide probably a better pace for starting.

If there is a CmdLet you want help with then one easy way to get to the Microsoft documentation is as follows:
Get-Help Where-Object -Online
Clearly you can change "Where-Object" for any other Microsoft CmdLet. The "-Online" option basically launches your default web browser.

Sometimes the documentation you want is more along the lines of "What was that command again?", well there is help! You remember it was something to do with items, in which case try Get-Command *item* and you will get a list of all the CmdLets with the word "item" somewhere in their name, nice!

Installing/Updating

If you need to update PowerShell, so for example, you need PowerShell 4.0 on Windows Server 2008 R2 then How to Install Windows PowerShell 4.0 - TechNet Articles is a very useful article.

Best Practice

It is always good to adopt "best practice" or at least be consistent. Working off a common standard helps everyone. Having your code reviewed and checked is also a good thing. Thus it is well worth checking out PSScriptAnalyzer details on which you can find at PowerShell/PSScriptAnalyzer: Download ScriptAnalyzer from PowerShellGallery with more help and advice at PSScriptAnalyzer deep dive – Part 1 of 4 – Hey, Scripting Guy! Blog.

Useful Cmdlets

These cmdlets are ones I have used and found helpful, clearly there are many more:

  • Get-WinEvent - the preferred option for Windows Event Logs
  • Get-Date - for all things date but this is not a Timespan
  • Start-Process - this is just brilliant
  • Start-Sleep - sleep or pause for a few milliseconds or seconds
  • Measure-Object - can count lines, words etc, however -Lines seems to ignore blank lines and lines of just whitespace, it can also process numbers and do this with CSV data too
  • Test-NetConnection - very handy for testing but only Windows 8/Server 2012 or higher, works with TCP and has a lot of diagnostic info
  • Test-Connection - very handy for testing, however it is ICMP based, note that it returns a lot more than it shows by default
  • Get-Uptime - this works in PowerShell core but I cannot find any documentation right now, it does have a "-Since" option
  • Invoke-RestMethod - call a REST service
For details on these and many other Cmdlets see Cmdlets which is a useful starting point. It is also worth being familiar with about_CommonParameters which applies to all Cmdlets.

Building on this, it is worth noting that when using Start-Process in a script called from IBM's Tivoli Workload Scheduler (TWS) I had to use -Wait, -RedirectStandardOutput and -NoNewWindow and then get the output file back in order to show the external process output on the console for TWS to pick up, skipping the redirect command caused some funny issues.

Variables

There are a number of handy variables which you can see at about_Automatic_Variables, however Introduction to Microsoft PowerShell – Variables is an excellent article to get a good overview and learn interesting tricks like:
dir variable:
Turns out the variables are loaded into a PowerShell drive like the Windows Registry and the File System.

Pausing and Keypresses

It seems that there are three options, a "read line" approach which requires the enter key to be pressed, a "detect key press" approach and a "message box" technique. None of them are especially hard. The simple "detect key press" is documented at Windows PowerShell Tip: Press Any Key to Continue and the "message box" is explained at Converting VBScript's MsgBox Function . The key press approach does not work from PowerShell ISE and so How to Properly Pause a PowerShell Script gives a more complete solution.

Windows Event Log

The easy way to parse, search or scan a Windows Event Log is to use the standard Event Viewer, which is either available standalone or via Computer Management. However you can also use PowerShell, which is much more flexible. The obvious cmdlet to use is Get-EventLog, however, whilst being good and flexible has a major issue, in that when working with a remote computer it drags everything local before filtering with Where-Object. So, the preferred cmdlet is Get-WinEvent which is harder to use but the investment is worth it, see Use PowerShell Cmdlet to Filter Event Log for Easy Parsing - Hey, Scripting Guy! Blog - Site Home - TechNet Blogs for more information on this.

Editors

My code editing tools of choice are Notepad++ and UltraEdit, and you will find more about them both on this website. However a "hard core" PowerShell scripting friend uses PowerGUI: Simplify your PowerShell and recommends it, so I am passing on his recommendation, because I respect his view, he said:

There are a couple of reasons why I like PowerGUI: You can single step through the script when testing/debugging. It has "Intellisense" style features that will offer the methods, variables and parameter names. Intellisense feature also works with SnapIns and Modules (SharePoint and Azure as an example) and once they have been run, any userdefined functions you have in the scripts.
So, well worth looking at!
Then there is Visual Studio of course, how could we miss that, so see Developing with VisualStudio for some details.

I have also seen POSHGUI which is "Free Online PowerShell Tools", not used it myself but worth a look.

This might also be worth considering: PowerShell Studio | The Most Powerful Windows PowerShell GUI Designer and Script Debugger Available

Having installed IntelliJ IDEA: The Java IDE for Professional Developers by JetBrains for Java development, I found that you can add a plugin for PowerShell support, and this is actually quite a usable solution. See ant-druha/PowerShell: Adds PowerShell language support to IntelliJ-based IDEs.

Shell Completion

If you type something like "Get-ChildItem -" and then press the tab key, on Windows with PowerShell you will get to cycle through the possible switches, one at a time. With PowerShell Core you get the whole list displayed. Interesting and handy.

Shell Changes

If you fancy changing the prompt in a PowerShell session then just enter the following at the prompt:

function prompt{
    $currentDirectory = Split-Path (Get-Location) -Leaf
    "PS: $currentDirectory\>"
}
This will change the prompt from something like: PS C:\Development\PowerShell\Demos>
To just this: PS Demos\>
If you prefer to just paste a single line then the following works
function prompt{ $currentDirectory = Split-Path (Get-Location) -Leaf ; "PS: $currentDirectory\>" }
This technique helps keep the prompt shorter and cleaner. This however is not a permanent change, it only applies to the current session. To make it permanent you would need to get the new "prompt" function into the profile. Read about_Prompts | Microsoft Docs for all the details on this and some more information on how the prompt function works.

Random Stuff to Sort!

PowerShell and Slack – Rambling Cookie Monster - using Slack from PowerShell

This is the starting point for several things PowerShell. The plan is to expand this over time but for now, if you need to get started then http://www.drdobbs.com/windows/powershell-for-developers-with-admin-tas/240150040 is a good place to start.

Also see the Regular Expression page for details for doing grep in PowerShell.

There is a nice script at Script PowerShell: Get Specific Files From Zip Files which is a good example of several things but primarily working with Zip files.

Desired State Configuration or DSC is supposed to be very good, note that Developers perspective on PowerShell Desired State Configuration – IndexOutOfRange is a good summary but is not an introduction or tutorial!

It is very easy to get PowerShell to generate HTML output and also not too hard to customise this output so it is easier to read, see Building HTML reports in PowerShell with ConvertTo-Html – 4sysops for details.

An interesting way to handle parameters, neatly: PowerShell splatting – 4sysops