4

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.)

not2qubit
  • 14,531
  • 8
  • 95
  • 135
  • 1
    i suspect you will need to use this module >> Windows Compatibility Module 1.0.0 for PowerShell Core 6 Released -- Microsoft Certified Professional Magazine Online — https://mcpmag.com/articles/2018/11/19/windows-compatibility-module-1.aspx – Lee_Dailey Feb 03 '19 at 23:01
  • 1
    Also see if you can find it when you run this `Get-Module NetSecurity -ListAvailable -SkipEditionCheck` – ArcSet Feb 03 '19 at 23:03
  • LoL! I'm not sure which answer fixed it, because when I ran `Import-Module NetSecurity -SkipEditionCheck` nothing seemed to happen (no output). So I went ahead and installed the `Install-Module WindowsCompatibility`, and then did the import again and all the `Get-Net*` was there! – not2qubit Feb 03 '19 at 23:38
  • PS. I added the `pwsh` tag to SO, since I think this a very important distinction to older *Windows PowerShell*. – not2qubit Feb 03 '19 at 23:44
  • 1
    Here's the link to the [WindowsCompatibility](https://www.powershellgallery.com/packages/WindowsCompatibility/1.0.0) module. with [github](https://github.com/PowerShell/WindowsCompatibility) – not2qubit Feb 03 '19 at 23:47
  • 1
    For reference, it's cmdlets. – Maximilian Burszley Feb 04 '19 at 00:51
  • @not2qubit: Use the existing `powershell-core` tag for PowerShell _Core_-related questions (I've done this for you). `pwsh` is just the name of the PowerShell Core _executable_. To see what happens when you call `Import-Module`, use `-Verbose`. It is the `-SkipEditionCheck` that did the trick in your case. – mklement0 Feb 04 '19 at 02:36
  • 1
    @TheIncorrigible1: Yes, what is pronounced "command-lets" is spelled _cmdlets_, but, strictly speaking, the properly abstract term is _commands_, given that some in-box functionality is implemented as (advanced) _functions_. – mklement0 Feb 04 '19 at 02:41
  • @mklement0 Thanks. But FYI, the `powershell-core` never appeared when I wrote `powershell`, which is why I added `pwsh`. Not sure what happened there. Too bad, because whatever you will call `powershell-core` in the future, most peolple will only know it as `pwsh`, because that is what they will see, use and type. I suggest make an alias tag to what I wrote since it by far explained much better what it means, and the differences between them. Your core tag essentially doesn't say diddly about what the difference is, nor telling the user when to use it. – not2qubit Feb 04 '19 at 11:37
  • 1
    @not2qubit: Not sure what happened in your case, because `powershell-core` definitely shows as a possible completion and its tag info does explain how it differs from the Windows PowerShell edition - and a product's _executable name_ doesn't necessarily tell the full story either (though, ideally, the two are the same). That said, I fully agree that `pwsh` makes sense as a tag _synonym_; in order to _nominate_ it as such, I had to create that tag again; now others need to _vote_ for the nomination for it to be implemented: https://stackoverflow.com/tags/powershell-core/synonyms – mklement0 Feb 04 '19 at 13:41
  • To bad I'm still not allowed to vote... Very complex and incomprehensible scoring algorithm there! 5 points here, 5 points there, but not on thursday and only during leap years when Jupiter is in ascension. – not2qubit Feb 04 '19 at 15:42

3 Answers3

3

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
ArcSet
  • 6,518
  • 1
  • 20
  • 34
  • Yes, the `Get-Mod...` found it, but the `Import-Module ...` didn't return anything confirming it was working. So you might need to add the `WindowsCompatibility` module... Since it now works, I'm happy to accept this answer. – not2qubit Feb 03 '19 at 23:41
  • So I guess the reason that *"NetSecurity is not supported in Core"*, is because the Core version is multiplatform? – not2qubit Feb 03 '19 at 23:43
  • I dont have Windows Compatibility Module and the command i posted worked. I think its because the firewall is very different in how it acts per OS. Yes Core is multiplatform – ArcSet Feb 03 '19 at 23:55
  • I just noticed that after restarting the (previously working) pwsh the cmdlet was gone. and I had to repeat the `Import-Module ...`. Any idea how to make it permament? – not2qubit Feb 04 '19 at 11:50
  • Thats a different question in and of its self because there are a few ways to do it based on the scope. All Shells, All Powershell shells, All Shells for just you and All powershells for just you. I wrote a script for that and if you post the question ill paste the script. But again this script would only work on windows machines – ArcSet Feb 04 '19 at 14:09
  • Well, it's not *that* different, I suppose most people expect that something you installed/imported to remain permanently. But I certainly now understand that the Windows module environment is unexpectedly different from what any common human logic could ever expect. – not2qubit Feb 04 '19 at 15:39
  • Well its not being installed. Thats a misconception. Its just loading those commands into the shell. You can make all you own commands also to load into the shell. So its more along the lines of saying hey this module exists do you need the commands right now type deal. The reason it doesnt happen automatically is the more commands the longer the shell takes to load – ArcSet Feb 04 '19 at 15:42
2

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)).

You cannot generally expect that to work.

As of this writing, older modules - created at a time when only Windows PowerShell existed - are in the process of being evaluated for PowerShell Core compatibility and, if the 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 (which causes PowerShell Core to ignore them by default), may also work in PowerShell Core, but only if they are implemented:

  • using PowerShell code only (*.psm1 files containing advanced functions acting like cmdlets)
  • and/or via CDXML, as in the case of the NetSecurity module.

Notably, this excludes modules that contain cmdlets, which invariably come as part of (invariably compiled) .NET assemblies, and/or contain helper DLLs (assemblies).

If you're unsure about the compatibility of a given older module (that doesn't explicitly (yet) which editions it is compatible with), you can use trial and error with -SkipEditionCheck (though inspecting the module's implementation - does it use .NET assemblies? - will give you a good sense beforehand).
However, given that modules that include .NET assemblies are more typical overall, I wouldn't expect many old modules to be compatible.

Conversely, if a 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 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 Core:

You have two options:

  • Use the WindowsCompatibility module, which uses implicit remoting to make Windows PowerShell-only cmdlets available in PowerShell Core, in the simplest case by communicating with Windows PowerShell on the same machine, but you can even target a machine remotely (in which case the commands will run there); once the module is installed, use Import-WinModule to import [proxy functions for] a given Windows PowerShell-only module.

    • Note that 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.
  • 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 similar limitations and caveats to using implicit remoting via the compatibility module. 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 }
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Ooh wow, I got a headache already. All I wanted to do was incorporating a cross-windows compatible PS one-liner to find out the windows firewall status, for a x-platform security-info module that lack proper Win support. This explains why it was not implemented, and why I will also give up implementing it, since it surely will not work unless the user is running latest Win10. – not2qubit Feb 04 '19 at 11:47
  • @not2qubit: Re one-liner: that's fairly easy to do, and you don't need the latest Windows 10 (but it won't be fast) - see my update. – mklement0 Feb 04 '19 at 13:56
  • @not2qubit: Re latest Windows 10: You don't _need_ it to apply the techniques in this answer: these work even on Windows 7. However, you will reduce the necessity of having to resort to these techniques if you use the latest Window 10 update channel. – mklement0 Feb 04 '19 at 15:01
  • Funny, I just added [this](https://stackoverflow.com/a/54516588/1147688) anser to another SO. (Same as your above.) But I think that just re-loading the `NetSecurity` module is faster than forking another shell like you did. But it's certainly useful to ses that option too. – not2qubit Feb 04 '19 at 15:27
  • 1
    @not2qubit: Well, the command I used to demonstrate calling `powershell.exe` came from your question :) But, yes, loading (importing) a module _in-process_ with `-SkipEditionCheck` - _if feasible_ - is always the best choice, for multiple reasons: performance, type fidelity, output-streams integration. – mklement0 Feb 04 '19 at 15:35
1

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.

js2010
  • 23,033
  • 6
  • 64
  • 66