not2qubit
not2qubit

Reputation: 16912

How to find or install missing Commands in PowerShell Core (pwsh)?

I am using multiple versions of PowerShell, but only 2 can find all standard commands (or is it commandlets?).

The original install is Windows PowerShell v5.1, but then I also have PowerShell Core (pwsh.exe) v6.1.1 installed.

The problem is that I am trying to run some firewall-related stuff in PowerShell Core, but the Get-NetFirewallProfile command cannot be found.

Get-NetFirewallProfile -Profile Domain, Public, Private | Select-Object Name, Enabled

However, it runs just fine in Windows PowerShell, since the required module NetSecurity is available there.

How can I make PowerShell Core either find the already existing modules or install them anew?
(Are they even compatible? - If not, how can they be updated?)


additional info

In PowerShell Core v6.1 I only have:

$ Get-Module -ListAvailable

    Directory: C:\Program Files\PowerShell\Modules

ModuleType Version    Name                                PSEdition ExportedCommands
---------- -------    ----                                --------- ----------------
Script     1.8.1      PSVersion                           Desk      {Get-PSVersion, Update-P
Binary     2.1.0.1    PSWindowsUpdate                     Desk      {Add-WUServiceManager, E

    Directory: C:\program files\powershell\6\Modules

ModuleType Version    Name                                PSEdition ExportedCommands
---------- -------    ----                                --------- ----------------
Manifest   6.1.0.0    CimCmdlets                          Core      {Get-CimAssociatedInstan
Manifest   1.2.2.0    Microsoft.PowerShell.Archive        Desk      {Compress-Archive, Expan
Manifest   6.1.0.0    Microsoft.PowerShell.Diagnostics    Core      {Get-WinEvent, New-WinEv
Manifest   6.1.0.0    Microsoft.PowerShell.Host           Core      {Start-Transcript, Stop-
Manifest   6.1.0.0    Microsoft.PowerShell.Management     Core      {Add-Content, Clear-Cont
Manifest   6.1.0.0    Microsoft.PowerShell.Security       Core      {Get-Acl, Set-Acl, Get-P
Manifest   6.1.0.0    Microsoft.PowerShell.Utility        Core      {Format-List, Format-Cus
Manifest   6.1.0.0    Microsoft.WSMan.Management          Core      {Disable-WSManCredSSP, E
Script     1.1.7.2    PackageManagement                   Desk      {Find-Package, Get-Packa
Script     1.6.7      PowerShellGet                       Desk      {Find-Command, Find-DSCR
Script     0.0        PSDesiredStateConfiguration         Desk      {GetSyntax, Write-MetaCo
Script     6.1.0.0    PSDiagnostics                       Core      {Disable-PSTrace, Disabl
Script     2.0.0      PSReadLine                          Desk      {Get-PSReadLineKeyHandle
Binary     1.1.2      ThreadJob                           Desk      Start-ThreadJob

whereas in Windows PowerShell v5.1, I have:

$ Get-Module -ListAvailable *

    Directory: C:\Program Files\WindowsPowerShell\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Binary     1.0.0.1    PackageManagement                   {Find-Package, Get
Script     1.0.0.1    PowerShellGet                       {Install-Module, F
Script     1.8.1      PSVersion                           {Get-PSVersion, Up

    Directory: C:\Windows\system32\WindowsPowerShell\v1.0\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   1.0.0.0    AppBackgroundTask                   {Disable-AppBackgr
Manifest   2.0.0.0    Appx                                {Add-AppxPackage,
Manifest   1.0.0.0    BitLocker                           {Unlock-BitLocker,
Manifest   1.0.0.0    BitsTransfer                        {Add-BitsFile, Com
Manifest   1.0.0.0    CimCmdlets                          {Get-CimAssociated
Manifest   1.0        Defender                            {Get-MpPreference,
Manifest   1.0.0.0    DirectAccessClientComponents        {Disable-DAManualE
Script     3.0        Dism                                {Add-AppxProvision
Manifest   1.0.0.0    DnsClient                           {Resolve-DnsName,
Manifest   2.0.0.0    International                       {Get-WinDefaultInp
Manifest   1.0.0.0    iSCSI                               {Get-IscsiTargetPo
Script     1.0.0.0    ISE                                 {New-IseSnippet, I
Manifest   1.0.0.0    Kds                                 {Add-KdsRootKey, G
Manifest   1.0.1.0    Microsoft.PowerShell.Archive        {Compress-Archive,
Manifest   3.0.0.0    Microsoft.PowerShell.Diagnostics    {Get-WinEvent, Get
Manifest   3.0.0.0    Microsoft.PowerShell.Host           {Start-Transcript,
Manifest   1.0.0.0    Microsoft.PowerShell.LocalAccounts  {Add-LocalGroupMem
Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Content, Clea
Script     1.0        Microsoft.PowerShell.ODataUtils     Export-ODataEndpoi
Manifest   3.0.0.0    Microsoft.PowerShell.Security       {Get-Acl, Set-Acl,
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Format-List, Form
Manifest   3.0.0.0    Microsoft.WSMan.Management          {Disable-WSManCred
Manifest   1.0        MMAgent                             {Disable-MMAgent,
Manifest   1.0.0.0    MsDtc                               {New-DtcDiagnostic
Manifest   2.0.0.0    NetAdapter                          {Disable-NetAdapte
Manifest   1.0.0.0    NetConnection                       {Get-NetConnection
Manifest   1.0.0.0    NetEventPacketCapture               {New-NetEventSessi
Manifest   2.0.0.0    NetLbfo                             {Add-NetLbfoTeamMe
Manifest   1.0.0.0    NetNat                              {Get-NetNat, Get-N
Manifest   2.0.0.0    NetQos                              {Get-NetQosPolicy,
Manifest   2.0.0.0    NetSecurity                         {Get-DAPolicyChang
Manifest   1.0.0.0    NetSwitchTeam                       {New-NetSwitchTeam
Manifest   1.0.0.0    NetTCPIP                            {Get-NetIPAddress,
Manifest   1.0.0.0    NetworkConnectivityStatus           {Get-DAConnectionS
Manifest   1.0.0.0    NetworkSwitchManager                {Disable-NetworkSw
Manifest   1.0.0.0    NetworkTransition                   {Add-NetIPHttpsCer
Manifest   1.0.0.0    PcsvDevice                          {Get-PcsvDevice, S
Manifest   1.0.0.0    PKI                                 {Add-CertificateEn
Manifest   1.1        PrintManagement                     {Add-Printer, Add-
Manifest   1.1        PSDesiredStateConfiguration         {Set-DscLocalConfi
Script     1.0.0.0    PSDiagnostics                       {Disable-PSTrace,
Binary     1.1.0.0    PSScheduledJob                      {New-JobTrigger, A
Manifest   1.5.2.6    PSWindowsUpdate                     {Add-WUOfflineSync
Manifest   2.0.0.0    PSWorkflow                          {New-PSWorkflowExe
Manifest   1.0.0.0    PSWorkflowUtility                   Invoke-AsWorkflow
Manifest   1.0.0.0    ScheduledTasks                      {Get-ScheduledTask
Manifest   2.0.0.0    SecureBoot                          {Confirm-SecureBoo
Manifest   2.0.0.0    SmbShare                            {Get-SmbShare, Rem
Manifest   2.0.0.0    SmbWitness                          {Get-SmbWitnessCli
Manifest   1.0.0.0    StartScreen                         {Export-StartLayou
Manifest   2.0.0.0    Storage                             {Add-InitiatorIdTo
Manifest   2.0.0.0    TLS                                 {New-TlsSessionTic
Manifest   1.0.0.0    TroubleshootingPack                 {Get-Troubleshooti
Manifest   2.0.0.0    TrustedPlatformModule               {Get-Tpm, Initiali
Manifest   2.0.0.0    VpnClient                           {Add-VpnConnection
Manifest   1.0.0.0    Wdac                                {Get-OdbcDriver, S
Manifest   1.0.0.0    WindowsDeveloperLicense             {Get-WindowsDevelo
Script     1.0        WindowsErrorReporting               {Enable-WindowsErr
Manifest   1.0.0.0    WindowsSearch                       {Get-WindowsSearch

And just in case someone wonders, all the available commands in a module can be listed with:
(Get-Module -ListAvailable NetSecurity).ExportedCommands

UPDATE:

I managed to find the correct modules, given a command/comdlet, using this:

(Get-Module -ListAvailable -SkipEditionCheck *).ExportedCommands.Values |select CommandType,Source,Version,Name | sort Name

(Alternatively replace ExportedCommands with ExportedCmdlets.)

Upvotes: 4

Views: 15702

Answers (3)

mklement0
mklement0

Reputation: 437197

ArcSet's helpful answer works in this case, but it's important to note that -SkipEditionCheck explicitly bypasses a given module's own [lack of] declaration of what PowerShell edition it works with: Desktop (Windows PowerShell) and/or Core (PowerShell (Core) 7).

  • Note that -SkipEditionCheck is only relevant to modules that ship with Windows, which are located in $env:SystemRoot\System32\WindowsPowerShell\v1.0\Modules

  • Modules in other locations are considered PowerShell 7-compatible by default, irrespective of whether a CompatiblePSEditions module-manifest entry is present or not, and, if present, what its value is. However, you can force loading such modules via the Windows compatibility feature via Import-Module -UseWindowsPowerShell.

You cannot generally expect -SkipEditionCheck to work.

As of this writing, older modules that ship with Windows - created at a time when only Windows PowerShell existed - are in the process of being evaluated for PowerShell 7 compatibility and, if they are, will be marked as such, via the new CompatiblePSEditions module-manifest entry.

Older modules that - invariably - were created for Windows PowerShell only and lack a CompatiblePSEditions declaration, may also work in PowerShell 7:

  • While PowerShell 7 is mostly backward-compatible with Windows PowerShell, differences in behavior do exist.

  • Similarly, binary cmdlets, which invariably come as part of (invariably compiled) .NET *assemblies, and/or contain helper DLLs (assemblies) may or may not work, depending on the differences between .NET Framework and .NET.

  • That said, as new Windows versions / updates are released, the list of modules that ship with Windows that do not explicitly indicate their edition compatibility will continue to shrink, and as of Windows 11 22H2, none of the ones that lack edition-compatibility information can be loaded directly into PowerShell 7, with -SkipEditionCheck.

If you're unsure about the compatibility of a given older module (that doesn't explicitly (yet) indicate which editions it is compatible with), you can use trial and error with
-SkipEditionCheck
.

Conversely, if a ships-with-Windows module does have a CompatiblePSEditions entry and indicates that the running edition is not supported, it's safe to assume that it will not work.

The PowerShellModuleCoverage GitHub repository [update: now obsolete] is dedicated to tracking issues with in-box modules once they've been marked as cross-edition and possibly modified to that end, which is an ongoing process as of this writing.
(For third-party modules, it is up to their maintainers to update them in that fashion.)

However, you'll only see the fruits of these efforts if you use the most recent Windows 10 version (update channel) and updates.

On older versions, including all the way back to Windows 7, you can still use -SkipEditionCheck to load older modules that you've tested and found to be implicitly compatible with PowerShell Core.


If / once you know that a given module doesn't work in PowerShell 7:

You have two options:

  • Option 1: Rely on the Windows PowerShell Compatibility feature, which uses implicit remoting to make Windows PowerShell-only modules available in PowerShell 7, by communicating with a hidden Windows PowerShell process on the same machine:

    • For ships-with-Windows modules that aren't marked as PowerShell Core (7) compatible, the compatibility feature is implicitly used.

    • For other incompatible modules, use Import-Module with the
      -UseWindowsPowerShell switch.

    • Caveat:

      • While implicit remoting may work as expected, it does have its limitations and is slower than in-process execution.

      • A notable limitation is that serialization and deserialization are involved, which means that only a limited number of types can be deserialized with type fidelity, whereas all others are deserialized as approximations of the original type, with static properties - see this answer for details.

  • Option 2: Ad-hoc: Call Windows PowerShell via its CLI, powershell.exe, passing an arbitrary command via a script block ({ ... }) - see example below.
    This comes with the same limitations and caveats as using the Windows PowerShell Compatibility feature. Also, since a new Windows PowerShell process is created for every invocation, you incur the overhead of starting it and importing the module of interest every time; if you need to run multiple commands, it's best to bundle them.

# Call the Windows PowerShell CLI from PowerShell Core, using a script block.
# (Add -noprofile to suppress $PROFILE loading.)
powershell { Get-NetFirewallProfile -Profile Domain, Public, Private | Select-Object Name, Enabled }

Upvotes: 2

js2010
js2010

Reputation: 27428

It looks like since Windows 10 version 1809, some of these missing commands are back in PS 6, like "get-netadapter" and "get-netfirewallrule". In fact 47 more modules available, mostly the "manifest" type.

Upvotes: 1

ArcSet
ArcSet

Reputation: 6860

NetSecurity is not supported in Core. If you are on a Windows OS you can however use the Param -SkipEditionCheck

Import-Module NetSecurity -SkipEditionCheck

You can use the same Param on Get-Module

Get-Module NetSecurity -ListAvailable -SkipEditionCheck

Upvotes: 3

Related Questions