Search code examples
powershellpowercli

Storing value of a variable as a type


Alright - really nitpicky, but i HATE writing the same code twice (even if at this point it would have saved me more time)

So I'm writing a PowerCLI function that has 2 switch parameters to either find a poweredon or poweredoff event.

behold

function pGet-PowerEvent {

[cmdletbinding()]

PARAM (

[parameter(ValueFromPipeline=$true,
Mandatory=$true,
Position=0)]
[string[]]
$Entity,

[parameter(ValueFromPipeline=$true,
Mandatory=$false,
Position=1)]
[switch]
$onEvent,

[parameter(ValueFromPipeline=$true,
Mandatory=$false,
Position=2)]
[Switch]
$offEvent

)

if ($onEvent) {
$EventType = "VmPoweredOnEvent"
}

if ($offEvent) {
$EventType = "VmPoweredOffEvent"
}

$entity.ForEach{write-host $_; Get-VIEvent -Entity $_ -MaxSamples([int]::MaxValue) | ?{$_ -is [vmware.vim."$EventType"] | 
select createdtime, username }

}

and running the command:

pGet-PowerEvent -Entity $vm -OnEvent

and the error:

Cannot convert the "[VMware.Vim.VmPoweredOffEvent]" value of type "System.String" to type "System.Type".

However when i run this command - it sees [vmware.vim.vmpoweredoffevent] as a string, rather than a type.

But i need the variable to be the type. And the value of the variable as the type.

Thanks


Solution

  • I believe you want either:

    Where-Object { $_.GetType().FullName -eq "vmware.vim.$EventType" }
    

    Or:

    Where-Object { $_ -is ([type]"vmware.vim.$EventType") }
    

    Or this may work better for you:

    Where-Object { $_.GetType().Name -eq $EventType }
    

    As an aside, you almost certainly don't want all three of your parameters to have ValueFromPipeline=$true.

    If you run this:

    Get-VM $VMName | pGet-PowerEvent
    

    It's basically identical to running this:

    $VM = Get-VM @VMParameters
    pGet-PowerEvent -Entity $VM -onEvent:$VM -offEvent:$VM
    

    You see how that doesn't make sense?

    Additionally, it doesn't really make sense to assign Position or Mandatory=$false to switch parameters. There is no reason you'd ever want to do this:

    pGet-PowerEvent $VI $true $false
    

    Instead of this:

    pGet-PowerEvent $VI -onEvent
    

    It's just much more readable. If you need to call it dynamically, you would want to do something like this:

    $OnEventSetting = (Get-Date).DayOfWeek -eq [DayOfWeek]::Monday
    $OffEventSetting = (Get-Date).DayOfWeek -eq [DayOfWeek]::Tuesday
    pGet-PowerEvent $VI -onEvent:$OnEventSetting -offEvent:$OffEventSetting