Site icon Think PowerShell

Using the Windows PowerShell Compatibility Module in PowerShell Core

Windows Compatibility Module is located in github.com

Access and use Windows PowerShell cmdlets from your PowerShell Core session on a Windows computer.

Missing cmdlets from PowerShell Core

In the last post, we installed PowerShell Core on a Windows computer. However, if you were to try using some common Windows PowerShell cmdlets from the session or via script, such as Get-WmiObject, you would get an error (below) because Get-WmiObject is a Windows PowerShell cmdlet and not part of PowerShell Core.

PS C:\Users\Demo> Get-WmiObject -Class Win32_ComputerSystem                                                             Get-WmiObject : The term 'Get-WmiObject' is not recognized as the name of a cmdlet, function, script file, or operable program.                                                                                                                 At line:1 char:1                                                                                                        + Get-WmiObject -Class Win32_ComputerSystem                                                                             + ~~~~~~~~~~~~~                                                                                                         + CategoryInfo          : ObjectNotFound: (Get-WmiObject:String) [], CommandNotFoundException                           + FullyQualifiedErrorId : CommandNotFoundException                                                                                                                 

Install Windows PowerShell Compatibility Module

Recognizing that in order to get Windows users to start installing and using PowerShell Core it had to be on par with Windows PowerShell, Microsoft released the Windows PowerShell Compatibility Module. This module makes Windows PowerShell cmdlets available from a PowerShell Core session.

Install the module using the Install-Module cmdlet. This will download and install the module from the PowerShell Gallery.

PS C:\Users\Demo> Install-Module WindowsCompatibility                                                                                                                                                                                           Untrusted repository                                                                                                    'PSGallery'?                                                                                                            [Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"): a
PS C:\Users\Demo>

And that’s it for installation! Let’s try running Get-WinModule to see the available modules. Depending on your current computer config, you may get the error below about being unable to connect. Why? Because the Windows PowerShell Compatibility Module uses implicit remoting.

PS C:\Users\Demo> Get-WinModule                                                                                         New-PSSession : [localhost] Connecting to remote server localhost failed with the following error message : The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig". For more information, see the about_Remote_Troubleshooting Help topic.                                                                                                                      At C:\Users\Demo\Documents\PowerShell\Modules\WindowsCompatibility\1.0.0\WindowsCompatibility.psm1:232 char:20          +         $session = New-PSSession @newPSSessionParameters | Select-Obj ...                                             +                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                              motingTransportException                                                                                                + FullyQualifiedErrorId : CannotConnect,PSSessionOpenFailed  

What is implicit remoting?

Explicit remoting is when you run Invoke-Command, where you are intentionally connecting to a remote computer and running cmdlets within a defined -ScriptBlock {}.

Implicit remoting is a method of taking a remote session (and its related modules) and exporting it to your local session. You can then transparently run cmdlets in your local session as if the cmdlets were installed locally. However they are not; when you run a cmdlet that was part of the remote session, it is seamlessly running them using the exported remote session.

Local WinRM required for Windows PowerShell Compatibility Module

Since the Windows PowerShell Compatibility Module depends on implicit remoting, and implicit remoting depends on WinRM, we need to ensure WinRM is enabled and configured on the local computer we are using PowerShell Core.

The quickest way to configure WinRM is to run the command winrm quickconfig.

PS C:\WINDOWS\system32> winrm quickconfig
WinRM is not set up to receive requests on this machine.
The following changes must be made:

Start the WinRM service.
Set the WinRM service type to delayed auto start.

Make these changes [y/n]? y

WinRM has been updated to receive requests.

WinRM service type changed successfully.
WinRM service started.

Using Windows PowerShell Compatibility Module

Once enabled, run Get-Module again to return the list of predefined modules that the Windows PowerShell Compatibility Module exposes:

PS C:\Users\Demo> Get-WinModule                                                                                                                                                                                                                 Name                                      Version   Description                                                         ----                                      -------   -----------                                                         AppBackgroundTask                         1.0.0.0                                                                       AppLocker                                 2.0.0.0                                                                       AppvClient                                1.0.0.0   Microsoft Application Virtualization Client Module                  Appx                                      2.0.1.0                                                                       AssignedAccess                            1.0.0.0                                                                       BitLocker                                 1.0.0.0                                                                       BitsTransfer                              2.0.0.0                                                                       BranchCache                               1.0.0.0                                                                       CimCmdlets                                1.0.0.0                                                                       ConfigCI                                  1.0                                                                           ConfigDefender                            1.0                                                                           Defender                                  1.0                                                                           DeliveryOptimization                      1.0.2.0                                                                       DirectAccessClientComponents              1.0.0.0                                                                       Dism                                      3.0                                                                           DnsClient                                 1.0.0.0                                                                       EventTracingManagement                    1.0.0.0                                                                       International                             2.0.0.0                                                                       iSCSI                                     1.0.0.0                                                                       ISE                                       1.0.0.0                                                                       Kds                                       1.0.0.0                                                                       Microsoft.PowerShell.Diagnostics          3.0.0.0                                                                       Microsoft.PowerShell.LocalAccounts        1.0.0.0   Provides cmdlets to work with local users and local groups          Microsoft.PowerShell.Management           3.1.0.0                                                                       Microsoft.PowerShell.ODataUtils           1.0
Microsoft.PowerShell.Operation.Validation 1.0.1
Microsoft.PowerShell.Security             3.0.0.0
Microsoft.PowerShell.Utility              3.1.0.0
Microsoft.WSMan.Management                3.0.0.0
MMAgent                                   1.0
MsDtc                                     1.0.0.0
NetAdapter                                2.0.0.0
NetConnection                             1.0.0.0
NetDiagnostics                            1.0.0.0
NetEventPacketCapture                     1.0.0.0
NetLbfo                                   2.0.0.0
NetNat                                    1.0.0.0
NetQos                                    2.0.0.0
NetSecurity                               2.0.0.0
NetSwitchTeam                             1.0.0.0
NetTCPIP                                  1.0.0.0
NetworkConnectivityStatus                 1.0.0.0
NetworkSwitchManager                      1.0.0.0
NetworkTransition                         1.0.0.0
PcsvDevice                                1.0.0.0
PersistentMemory                          1.0.0.0
Pester                                    3.4.0     Pester provides a framework for running BDD style Tests to execute… PKI                                       1.0.0.0
PnpDevice                                 1.0.0.0
PrintManagement                           1.1
ProcessMitigations                        1.0.11
Provisioning                              3.0
PSDesiredStateConfiguration               1.1
PSDiagnostics                             1.0.0.0
PSScheduledJob                            1.1.0.0
PSWorkflow                                2.0.0.0
PSWorkflowUtility                         1.0.0.0
ScheduledTasks                            1.0.0.0
SecureBoot                                2.0.0.0
SmbShare                                  2.0.0.0
SmbWitness                                2.0.0.0
StartLayout                               1.0.0.0
Storage                                   2.0.0.0
StorageBusCache                           1.0.0.0
TLS                                       2.0.0.0
TroubleshootingPack                       1.0.0.0
TrustedPlatformModule                     2.0.0.0
UEV                                       2.1.639.0 User Experience Virtualization management commands.
VpnClient                                 2.0.0.0
Wdac                                      1.0.0.0
Whea                                      2.0.0.0
WindowsDeveloperLicense                   1.0.0.0
WindowsErrorReporting                     1.0
WindowsSearch                             1.0.0.0
WindowsUpdate                             1.0.0.0
WindowsUpdateProvider                     1.0.0.2

Using Get-Command, we can demonstrate that some Windows PowerShell cmdlets are now available directly, such as Get-ScheduledTask:

PS C:\Users\Demo> Get-Command *ScheduledTask*                                                                                                                                                                                                   CommandType     Name                                 Version    Source
-----------     ----                                 -------    ------
Function        Disable-ScheduledTask                1.0.0.0    ScheduledTasks
Function        Enable-ScheduledTask                 1.0.0.0    ScheduledTasks
Function        Export-ScheduledTask                 1.0.0.0    ScheduledTasks
Function        Get-ClusteredScheduledTask           1.0.0.0    ScheduledTasks
Function        Get-ScheduledTask                    1.0.0.0    ScheduledTasks
Function        Get-ScheduledTaskInfo                1.0.0.0    ScheduledTasks
Function        New-ScheduledTask                    1.0.0.0    ScheduledTasks
Function        New-ScheduledTaskAction              1.0.0.0    ScheduledTasks
Function        New-ScheduledTaskPrincipal           1.0.0.0    ScheduledTasks
Function        New-ScheduledTaskSettingsSet         1.0.0.0    ScheduledTasks
Function        New-ScheduledTaskTrigger             1.0.0.0    ScheduledTasks
Function        Register-ClusteredScheduledTask      1.0.0.0    ScheduledTasks
Function        Register-ScheduledTask               1.0.0.0    ScheduledTasks
Function        Set-ClusteredScheduledTask           1.0.0.0    ScheduledTasks
Function        Set-ScheduledTask                    1.0.0.0    ScheduledTasks
Function        Start-ScheduledTask                  1.0.0.0    ScheduledTasks
Function        Stop-ScheduledTask                   1.0.0.0    ScheduledTasks
Function        Unregister-ClusteredScheduledTask    1.0.0.0    ScheduledTasks
Function        Unregister-ScheduledTask             1.0.0.0    ScheduledTasks

We can then run Get-ScheduledTask directly:

PS C:\Users\Demo> Get-ScheduledTask                                                                                                                                                                                                             TaskPath                                       TaskName                          State
--------                                       --------                          -----
\                                              OneDrive Standalone Update Task-… Ready
\Microsoft\Windows\.NET Framework\             .NET Framework NGEN v4.0.30319    Ready
\Microsoft\Windows\.NET Framework\             .NET Framework NGEN v4.0.30319 64 Ready
\Microsoft\Windows\.NET Framework\             .NET Framework NGEN v4.0.30319 6… Disabled
\Microsoft\Windows\.NET Framework\             .NET Framework NGEN v4.0.30319 C… Disabled
\Microsoft\Windows\Active Directory Rights Ma… AD RMS Rights Policy Template Ma… Disabled
\Microsoft\Windows\Active Directory Rights Ma… AD RMS Rights Policy Template Ma… Ready
\Microsoft\Windows\AppID\                      PolicyConverter                   Disabled
\Microsoft\Windows\AppID\                      VerifiedPublisherCertStoreCheck   Disabled
\Microsoft\Windows\Application Experience\     Microsoft Compatibility Appraiser Ready
\Microsoft\Windows\Application Experience\     ProgramDataUpdater                Ready
...

Some cmdlets require using Invoke-WinCommand

When you run Get-WinModule, we still don’t see Get-WmiObject. While we can’t run that directly within PowerShell Core, the Windows Compatibility Module adds the Invoke-WinCommand cmdlet to enable running additional Windows cmdlets.

Invoke-WinCommand takes a script block and runs it within the compatibility runspace. By default when executing, the current compatibility session is used.

To demonstrate, let’s try to run Get-WmiObject directly again:

Windows TerminalPS C:\Users\Demo> Get-WmiObject -Class Win32_ComputerSystem                                                             
Get-WmiObject : The term 'Get-WmiObject' is not recognized as the name of a cmdlet, function, script file, or operable p
rogram.                                                                                                                 
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.               
At line:1 char:1                                                                                                        
+ Get-WmiObject -Class Win32_ComputerSystem                                                                             
+ ~~~~~~~~~~~~~                                                                                                         
+ CategoryInfo          : ObjectNotFound: (Get-WmiObject:String) [], CommandNotFoundException                           
+ FullyQualifiedErrorId : CommandNotFoundException

Now let’s use Invoke-WinCommand, wrapping Get-WmiOjbect in a ScriptBlock:

PS C:\Users\Demo> Invoke-WinCommand -ScriptBlock {Get-WmiObject -Class Win32_ComputerSystem}                                                                                                                                                    Domain              : WORKGROUP                                                                                         Manufacturer        : Microsoft Corporation                                                                             Model               : Virtual Machine                                                                                   Name                : DESKTOP-D17T4N5                                                                                   PrimaryOwnerName    : Demo                                                                                              TotalPhysicalMemory : 3547197440                                                                                        PSComputerName      : localhost

It works! You can store the result of Invoke-WinCommand in a variable for later use in your script:

PS C:\Users\Demo> $result = Invoke-WinCommand -ScriptBlock {Get-WmiObject -Class Win32_ComputerSystem}                  
PS C:\Users\Demo> $result                                                                                                                                                                                                                       Domain              : WORKGROUP                                                                                         Manufacturer        : Microsoft Corporation                                                                             Model               : Virtual Machine                                                                                   Name                : DESKTOP-D17T4N5                                                                                   PrimaryOwnerName    : Demo                                                                                              TotalPhysicalMemory : 3547197440                                                                                        PSComputerName      : localhost 

What’s next for Windows Compatibility Module

I started the initial draft for this post a while ago, and a LOT has changed since then. Microsoft recognized that they had to unify PowerShell Core and Windows PowerShell, and that is the intent with PowerShell 7 (note the lack of “Core” or “Windows” in the name).

PowerShell 7 should be available soon, as it will closely follow on the .NET Core release cycle (which will eventually become .NET 5). Eventually, the Windows Compatibility Module will no longer be required.

Exit mobile version