2017-08-20 3 views
1

Ich habe eine erweiterte Funktion erstellt, um die MAC-Adresse von einer VM zu erhalten, die auf VMware ESXi läuft.PowerShell erweiterte Funktionsausgabe PipelineVariable funktioniert nicht

function Get-MacFromVm { 
    [CmdletBinding(SupportsShouldProcess=$true)] 
    Param(
     # The name of the VM of which we want to obtain the mac address. 
     [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true, 
        ValueFromPipelineByPropertyName=$true)] 
     [string[]] 
     $Name 
    ) 

    Begin {} 
    Process { 
     foreach ($item in $Name) { 
      if ($PSCmdlet.ShouldProcess($item, "Getting the mac address")) { 
       Get-VM $item -PipelineVariable vm | 
        Get-NetworkAdapter | 
        Select-Object @{n="Name"; e={$vm.Name}}, 
         @{n="ClientId"; e={$_.MacAddress -replace ":","-"}} 
      } 
     } 
    } 
    End {} 
} 

Bis jetzt funktioniert alles perfekt. Ich kann es auf eine der folgenden Arten verwenden und Ergebnisse zurück erhalten.

Er akzeptiert entweder ein einzelnes oder ein Array von Strings über den benannten Parameter oder als Pipeline-Eingang.

Get-MacFromVm -Name "playground" 
Get-MacFromVm -Name "playground", "DC01" 
"playground", "DC01" | Get-MacFromVm 

Der Ausgang ist eine [PSCustomObject] mit 2 Eigenschaften, einen Namen und die ClientId.

Jetzt beginnt das Problem, wenn ich das Ergebnis mit dem Parameter -PipelineVariable auf mehrere andere Cmdlets verketten möchte.

Normalerweise sollte ich in der Lage sein, es wie folgt zu verwenden:

Get-MacFromVm -Name "playground" -PipelineVariable pv | % {$pv} 

Aber es macht mir keine Ergebnisse zeigen, zurück. Wenn ich die $pv durch $_ ersetze, zeigt es das korrekte Ergebnis, aber ich kann diese automatische Variable 2 oder 3 Cmdlets weiter in der Pipelinekette nicht verwenden.

Obwohl ich dies lösen kann, indem Sie die -OutVariable verwenden und/oder in mehrere Zeilen aufteilen. Ich möchte wissen, warum das nicht funktioniert, ich möchte wissen, was ich hier vermisse.

+0

Was ist Ihre PowerShell-Version? –

+0

5.1.15063.483 unter Windows 10. – Adamar

Antwort

0

Ich habe keine Erfahrung mit -PipelineVariable Parameter. So nahm ich dies als eine Gelegenheit, über die -PipelineVariable Parameter zu lernen:

Weil ich einen einfachen Zugang zu VMs auch nicht, ich die Funktion wie folgt simuliert:

Function Get-MacFromVm { 
    [CmdletBinding(SupportsShouldProcess=$true)] 
    Param(
     [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true, 
        ValueFromPipelineByPropertyName=$true)] 
     [string[]] 
     $Name 
    ) 
    Function MacAddress {(1..4 | ForEach {'{0:x2}' -f (Get-Random -Min 0 -Max 255)}) -Join ":"} 
    Function Get-VM {[cmdletbinding()] Param ($Name) [pscustomobject]@{Name = $Name; MacAddress = (MacAddress)}} 
    ForEach ($Item in $Name) { 
     If ($PSCmdlet.ShouldProcess($Item, "Getting the mac address")) { 
      Get-VM $item -PipelineVariable vm | 
      Select-Object @{n="Name"; e={$vm.Name}}, @{n="ClientId"; e={$_.MacAddress -replace ":","-"}} 
     } 
    } 
} 

Aber ich bin nicht in der Lage reproduzieren das Problem:

PS C:\> Get-MacFromVm -Name "playground", "DC01" -PipelineVariable pv | % {$pv} 

Name  ClientId 
----  -------- 
playground 3c-23-55-c4 
DC01  4f-38-42-a7 

Also frage ich mich, ob diese simulierte Funktion auch für Sie funktioniert.
Wenn ja, können Sie vielleicht die Unterschiede zu einem echten VM-Objekt finden.

Mit PowerShell würde ich in Frage stellen, ob nichts ausgegeben oder nichts angezeigt wird. Also, was passiert, wenn Sie nur Ausgang eine einzige Eigenschaft:

Get-MacFromVm -Name "playground" -PipelineVariable pv | % {$pv.Name} 

Oder:

Get-MacFromVm -Name "playground" -PipelineVariable pv | % {$pv.GetType()} 

dies einen "You cannot call a method on a null-valued expression." Fehler zurückgibt?

+0

Mit Ihrem modifizierten Code funktioniert es wie erwartet. Aber mit meinem eigenen tut es nicht. Und das ist ein Ja zu Ihrer letzten Frage, ich bekomme tatsächlich den "nullwertigen" Fehler. Soweit ich weiß, ist alles, was ich ausgib, ein Objekt in der Pipeline, also sollte es egal sein, was das VMware-Cmdlet gibt, das auch nur ein Objekt ist. – Adamar

+0

Der 'Get-VM'-Befehl gibt einen' UniversalVirtualMachineImpl' von 'VMware.VimAutomation.ViCore.Impl.V1 zurück.Inventory.InventoryItemImpl' Basistyp. – Adamar