Reputation: 8868
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
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
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+.
-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:
Add-Type: Assembly with same name is already loaded.
, Operation is not supported on this platform (0x80131539)
), which are suppressed with -ErrorAction Ignore
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