Doug Maurer
Doug Maurer

Reputation: 8868

-PipelineVariable not working on Get-NetIPAddress

I'm obviously failing to understand the nuances to -PipelineVariable

If I pass Get-NetIPAddress into Get-NetAdapter it shows the associated adapters.

Get-NetIPAddress | Get-NetAdapter -ErrorAction SilentlyContinue

Now if I want to also collect the IP I decided I'd just tack it on

Get-NetIPAddress -PipelineVariable ip | Get-NetAdapter -ErrorAction SilentlyContinue | Select-Object *,@{n='IP';e={$ip.IPAddress}}

However I see the error

Get-NetIPAddress : Cannot retrieve the dynamic parameters for the cmdlet. Object reference not set to an instance of an object.
At line:1 char:5
+     Get-NetIPAddress -PipelineVariable ip

Even just simply running this gets the same error

Get-NetIPAddress -PipelineVariable ip | Get-NetAdapter -ErrorAction SilentlyContinue

This also returns the same error.

Get-NetIPAddress -PipelineVariable ip | Get-NetAdapter -ErrorAction SilentlyContinue | ForEach-Object {
            [PSCustomObject]@{
                Name      = $_.Name
                IfDesc    = $_.Interfacedescription
                IfIndex   = $_.ifindex
                MAC       = $_.macaddress
                LinkSpeed = $_.linkspeed
                IP        = $ip.IPAddress
            }
        }

Is this not how it was intended to be used? Originally I was using Where-Object to filter against IPv4 address family, but omitted it for this example.

Working around it like this just seems wrong.

foreach($ip in Get-NetIPAddress){
    $ip | Get-NetAdapter -ErrorAction SilentlyContinue | ForEach-Object {
        [PSCustomObject]@{
            Name      = $_.Name
            IfDesc    = $_.Interfacedescription
            IfIndex   = $_.ifindex
            MAC       = $_.macaddress
            LinkSpeed = $_.linkspeed
            IP        = $ip.IPAddress
        }
    }
}

Upvotes: 2

Views: 473

Answers (1)

mklement0
mklement0

Reputation: 437090

It seems that you're seeing a bug in Windows PowerShell that affects all so-called CDXML cmdlets, of which Get-NetIPAddress is one instance.

  • CDXML cmdlets are implemented declaratively via *.cdxml XML documents that define a "mapping between PowerShell cmdlets and CIM class operations or methods."

Seemingly, in Windows PowerShell no CDXML cmdlets support the common -PipelineVariable parameter and report the Cannot retrieve the dynamic parameters for the cmdlet error you saw:

# !! Fails in Windows PowerShell.
# OK in PowerShell (Core) v7.2+
PS> Get-NetIPAddress -PipelineVariable var | 
      Select IPAddress, @{ Name='IPAddressViaPipelineVar'; Expression = { $var.IPAddress } }

Get-NetIPAddress : Cannot retrieve the dynamic parameters for the cmdlet. Object reference not set to an instance of an object.

Note:


In PowerShell (Core) 7+:

  • The bug has been fixed in v7.2+.

    • However, there is a related bug, still present as of v7.3.8: If you use -PipelineVariable with a CDXML cmdlet and another CDXML cmdlet is used in the same pipeline (without -PipelineVariable), the latter unexpectedly resets the pipeline variable to $null - see GitHub issue #20546.

Caveat: I'm unclear on the official maintenance status of CDXML cmdlets:

  • The linked CDXML documentation is marked as no longer being updated.

  • In the still-maintained documentation, CDXML cmdlets are only mentioned in passing, in the conceptual about_CimSession help topic.

  • PowerShell (Core) uses the very same CDXML modules that Windows PowerShell does: they come with Windows PowerShell (in subfolders of C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules). However, there is an edition-specific, dynamic transformation step involved, namely the transformation of the *.cdxml XML files into PowerShell functions, which then use edition-specific types such as [Microsoft.Management.Infrastructure.CimInstance].

The following command lists all locally available modules that contain CDXML cmdlets:

  • Note: This takes quite a while and explicitly imports all locally available into the current session, so that all function bodies can be examined.

  • In PowerShell (Core) 7+ - but not in Windows PowerShell - the following problems occur:

    • Errors are reported (Add-Type: Assembly with same name is already loaded., Operation is not supported on this platform (0x80131539)), which are suppressed with -ErrorAction Ignore
    • Implicit remoting modules are created, presumably via the Windows PowerShell Compatibility feature.
    • Most of the modules do not report the set of exported functions, and show a version number of 0.0.
Get-Command -Type Function | 
  % { if (-not $_.Module) { return } Import-Module -WarningAction Ignore -EA Ignore $_.Module; if ((Get-Content -EA Ignore "function:$($_.Name)") -match 'cdxml') { $_.Module } } | 
    Sort-Object Name, @{ Expression={ $_.Version }; Descending=$true } -Unique

Upvotes: 3

Related Questions