Search code examples
powershellpipelinepscustomobject

Powershell Object not being piped through to Functions


I have two functions one creates a custom object which once done is piped to the next function. The problem is that the second function is not receiving my object correctly. Instead of using the pipeline I have tried setting a variable and then piping that variable to the function. Below are the two functions with the output of get member on the returned object. All the string param are being processed correctly. But the objects simply wont work. In the begin block of the New-BaseGuest I am not able to assign the results to the variables.

Basically I want to end up with:

Get-ServerFromXML -XMLFile File -GuestName Name | New-BaseGuest

The New-BaseGuest function is incomplete as I cannot get the parameters working.

TypeName: System.Management.Automation.PSCustomObject

Name             MemberType   Definition                     
----             ----------   ----------                     
Equals           Method       bool Equals(System.Object obj) 
GetHashCode      Method       int GetHashCode()              
GetType          Method       type GetType()                 
ToString         Method       string ToString()              
CDROM_Connected  NoteProperty object CDROM_Connected=null    
CDROM_ISO        NoteProperty object CDROM_ISO=null          
Floppy_Connected NoteProperty object Floppy_Connected=null   
Floppy_ISO       NoteProperty object Floppy_ISO=null         
GuestType        NoteProperty string GuestType=vmkernel6Guest
IPAddress        NoteProperty string IPAddress=192.168.199.40
ServerName       NoteProperty string ServerName=ESX-VSAN3    
vCPU             NoteProperty string vCPU=2                  
vHDD             NoteProperty Object[] vHDD=System.Object[]  
vNIC             NoteProperty Object[] vNIC=System.Object[]  
vRAM             NoteProperty string vRAM=5120   


function Get-ServerFromXML
{
 <##>

[CmdletBinding()]
param
(
    [String]
    $XMLFile,

    [String]
    $GuestName
)
$xml = New-Object -TypeName XML
$xml.Load($XMLFile)
$Server = Select-Xml -Xml $xml -XPath ('/Servers/Server[@Name = "' + $GuestName + '" ]')
$vNicObjs = @()
$vHddobjs = @()
If ($Server.Node.Hardware.vnic.Count -ne $null)
{
    $Server.Node.Hardware.vnic | %{
        $NicProps = @{
            NIC_ID = $_.ID;
            NIC_Type = $_.Type;
            NIC_StartConnected = $_.StartConnected;
            NIC_MACAddress = $_.MACAddress;
            NIC_WakeOnLan = $_.WakeOnLan;
            NIC_PortGroup = $_.PortGroup
        }
        $vNicObj = New-Object -TypeName System.Management.Automation.PSObject -Property $NicProps
        $vNicObjs += $vNicObj
    }
}
Else
{
    $NicProps = @{
        NIC_ID = $Server.Node.Hardware.vnic.ID;
        NIC_Type = $Server.Node.Hardware.vnic.Type;
        NIC_StartConnected = $Server.Node.Hardware.vnic.StartConnected;
        NIC_MACAddress = $Server.Node.Hardware.vnic.MACAddress;
        NIC_WakeOnLan = $Server.Node.Hardware.vnic.WakeOnLan;
        NIC_PortGroup = $Server.Node.Hardware.vnic.PortGroup
    }
        $vNivObj = New-Object -TypeName System.Management.Automation.PSObject -Property $NicProps
        $vNicObjs += $vNivObj
}

If ($Server.Node.Hardware.vHDD.Count -ne $null)
{
    $Server.Node.Hardware.vHDD | %{
        $HDDProps = @{
            HDD_ID = $_.ID;
            HDD_Type = $_.Type;
            HDD_Size = $Server.Node.Hardware.vHDD.Size;
            HDD_Datastore = $_.Datastore;
            HDD_StorageFormate = $_.StorageFormat
        }
        $vHDDObj = New-Object -TypeName System.Management.Automation.PSObject -Property $HDDProps
        $vHDDObjs += $vHDDObj
    }
}
Else
{
    $HDDProps = @{
        HDD_ID = $Server.Node.Hardware.vHDD.ID;
        HDD_Type = $Server.Node.Hardware.vHDD.Type;
        HDD_Size = $Server.Node.Hardware.vHDD.Size;
        HDD_DataStore = $Server.Node.Hardware.vHDD.Datastore;
        HDD_StorageFormat = $Server.Node.Hardware.vHDD.StorageFormat
    }
    $vHDDObj = New-Object -TypeName System.Management.Automation.PSObject -Property $HDDProps
    $vHDDObjs += $vHDDObj
}


$ServerProps =[Ordered]@{
    ServerName = $Server.Node.Description.Name;
    GuestType = $Server.Node.Description.GuestType;
    IPAddress = $Server.Node.Description.PrimaryIP;
    vCPU = $Server.Node.Hardware.vCPU;
    vRAM = $Server.Node.Hardware.vRAM;
    vHDD = $vHddobjs;
    vNIC = $vNicObjs;
    CDROM_ISO = $Server.Node.Hardware.CDROM.ISOPath
    CDROM_Connected = $Server.Node.Hardware.CDROM.StartConnected
    Floppy_ISO = $Server.Node.Hardware.Floppy.ISOPath
    Floppy_Connected = $Server.Node.Hardware.Floppy.StartConnected
}

$ServerObj = New-Object -TypeName System.Management.Automation.PSObject -Property $ServerProps
$ServerObj
}

function New-BaseGuest
{
 <##>

[CmdletBinding(PositionalBinding = $true,
               SupportsShouldProcess = $true)]
param
(
    [Parameter(Mandatory = $true,
               ValueFromPipeline = $false,
               ValueFromPipelineByPropertyName = $true,
               Position = 1)]
    [string]
    $ServerName,

    [Parameter(Mandatory = $true,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 2)]
    [string]
    $GuestType,

    [Parameter(Mandatory = $true,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 3)]
    [string]
    $vCPU,

    [Parameter(Mandatory = $true,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 4)]
    [string]
    $vRAM,

    [Parameter(Mandatory = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 5)]
    [system.object]
    $vHDD,

    [Parameter(Mandatory = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 6)]
    [system.object]
    $vNIC,

    [Parameter(Mandatory = $false,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 7)]
    [string]
    $CDROM_ISO = $Null,

    [Parameter(Mandatory = $false,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 8)]
    [string]
    $FLOPPY_ISO = $Null,

    [Parameter(Mandatory = $false,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 9)]
    [string]
    $CDROM_Connected = $Null,

    [Parameter(Mandatory = $true,
               ValueFromPipeline = $true,
               ValueFromPipelineByPropertyName = $true,
               Position = 10)]
    [string]
    $Floppy_Connected = $Null
)

BEGIN 
{
    $Datastore  = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_DataStore).HDD_DataStore
    $PortGroup  = ($vNIC | Where-Object { $_.NIC_ID -eq 1 } | Select-Object -Property NIC_PortGroup).NIC_PortGroup
    $DiskSize   = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_Size).HDD_Size
    $DiskFormat = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_StorageFormat).HDD_StorageFormat
}
PROCESS
{
    New-VM -Name $ServerName `
           -Datastore $Datastore `
           -NumCPU $vCPU `
           -MemoryGB $vRAM`
           -DiskGB $DiskSize `
           -NetworkName $PortGroup `
           -DiskStorageFormat $CDROM_ISO `
           -GuestID $GuestType | Out-Null
}
END
{

}
}

Solution

  • This is expected behavior. The begin {} block runs before any pipeline objects are encountered, so you have no access to any parameters that come in through the pipeline in your begin block.

    The process {} block is run once for each item, so the code you have in the begin block really needs to be put there (because it's specific to a single VM).