- Interact with Azure Cosmos DB with PowerShell - Tue, Sep 14 2021
- Azure health services: Track Microsoft cloud outages and maintenance - Wed, Sep 8 2021
- Powerline: Customize your PowerShell console - Tue, Aug 31 2021
If you want to use PowerShell to automate administration on Windows systems, then you have quite a few PowerShell versions to choose from:
- PowerShell 5.1 (called "Windows PowerShell")
- PowerShell 6.x (called "PowerShell Core")
- PowerShell 7.x (called simply "PowerShell")
Which of these is applicable to the work you're doing? Read on to find out.
PowerShell 5.1—Windows only ^
PowerShell v5.1 is no longer under active development because Microsoft wants PowerShell to be a universal task automation language, usable in Windows, macOS, and Linux. According to the PowerShell team, Microsoft will continue shipping PowerShell v5.1 in Windows Server and Windows 10, but eventually plans to ship PowerShell v7 side-by-side with v5.1.
Thus, we can expect Microsoft to service PowerShell v5.1 periodically with bug fixes and security updates, but not with any new functionality.
Why is PowerShell v5.1 Windows-only? Because the platform relies on the .NET Framework runtime environment, which runs only on Microsoft Windows. Here's what the $PSVersionTable automatic variable outpoint looks like on my Windows Server 2019 system:
PowerShell 5.1—No ISE ^
Besides PowerShell v5.1, guess what else relies on the Windows-only .NET Framework? You guessed it—the PowerShell Integrated Scripting Environment (ISE), shown in the following figure.
Therefore, you cannot use PowerShell ISE with PowerShell v6 or v7.
As convenient as the ISE is, the tool no longer has any future. Consequently, you should shift your development environment over to Visual Studio Code or another integrated development environment (IDE) as soon as possible.
Specifically, I suggest you install Microsoft's PowerShell extension in VS Code so you have full support for the PowerShell language in your scripts. As you can see in the next screenshot, on Windows systems you can choose which PowerShell version you want to use in VS Code's integrated terminal:
PowerShell 7—Cross-platform ^
Microsoft created the .NET Core runtime environment to support cross-platform development. Accordingly, PowerShell v6.x is the first PowerShell version written for .NET Core; it runs on Windows, macOS, and Linux.
In PowerShell Core v6, Microsoft used their .NET Standard specification; .NET Standard apps can run inside either .NET Framework or .NET Core-based systems.
.NET Core and PowerShell v6.x are both open source at GitHub, which represents a gigantic leap forward for Microsoft. Now the technical community at large can not only inspect Microsoft's source code, but can even make contributions!
PowerShell Core v6.2 is the final generally available PowerShell Core v6.2 release. The latest PowerShell version is called PowerShell 7, and this is the version I suggest you and your team standardize upon. For this reason, I'll compare PowerShell v5.1 only with PowerShell 7 from now on.
Here's the $PSVersionTable output on the same Windows Server 2019 system in my test lab:
The PowerShell team designed PowerShell v7 such that it can be installed side-by-side with PowerShell v5.1. That said, you definitely need to understand that PowerShell v5.1 and PowerShell v7 have separate module paths. Check 'em out in the following figures:
Note that my system has some module paths you might not have due to additional products I've installed.
The two PowerShell versions also have separate profile paths:
- PowerShell v5.1: $HOME\Documents\WindowsPowerShell
- PowerShell v7: $HOME\Documents\PowerShell
PowerShell v7 now supports Secure Shell (SSH)-based remoting in addition to the traditional WS-Management remoting. I wrote a 4sysops tutorial on PowerShell v7 SSH remoting not too long ago.
PowerShell 7—Backward compatibility ^
Okay, now we get to what is truly the heart of the matter—what do we lose by standardizing on PowerShell v7?
Well, it's not so much what you lose as it is what you'll have to adapt to in the short to medium term. The big issue is module compatibility. The PowerShell team has been working really hard to ensure PowerShell v7 is compatible with earlier modules written for the .NET Framework and PowerShell v5.1. Microsoft calls these modules "Windows PowerShell modules."
PowerShell v6.x included a WindowsCompatibility module, but the team integrated that functionality into v7 natively so we don't have to install anything extra.
One way to load Windows PowerShell modules in PowerShell v7 is to invoke the -UseWindowsPowerShell switch parameter of the Import-Module command.
For example, let's say I need to work with the ADSync module on my Windows Server 2019 Azure AD Connect server. As you can see in the following screenshot, attempting to load and use the module in PowerShell v7 initially fails:
However, when we employ the -UseWindowsPowerShell switch, the module load succeeds and we're able to use the Azure AD Connect PowerShell commands, seemingly under PowerShell v7. What's going on here?
When you invoke -UseWindowsPowerShell, the following actions occur:
- PowerShell v7 uses implicit remoting to create local aliases to the source commands.
- The .NET Framework module is actually loaded in a PowerShell v5.1 session behind the scenes.
- Any objects you retrieve from a session are incomplete.
The third bullet point bears further explanation. Notice the methods available for the Get-ADSyncScheduler cmdlet under Windows PowerShell v5.1:
Now contrast that methods list with the following screenshot, which shows output under PowerShell v7 implicit remoting:
Using the implicit remoting module loading method results in your Windows PowerShell commands running in a separate, hidden session. Thus, the objects that are returned to your PowerShell v7 pipeline are deserialized objects, not the original types.
The other way to invoke the PowerShell v7 compatibility feature is to perform module autoload or explicit module loading of a supported module. For example, the ActiveDirectory Windows PowerShell module can be called within PowerShell v7 through command discovery or an Import-Module command. Review the list of natively compatible modules in the Microsoft Docs library.
While we're at it, you should also study the About Windows PowerShell Compatibility conceptual help article.
So do you have the lay of the land now? Let me sum up my recommendations:
Subscribe to 4sysops newsletter!
- Skip PowerShell Core v6 and load the latest supported PowerShell v7 engine.
- Install Visual Studio Code and commit to using PowerShell v7 wherever possible.
- Keep abreast of the ever-expanding compatible modules list, and don't forget about the Import-Module command's -UseWindowsPowerShell switch parameter.