Only show property if a condition is met on [PScustomObject]

I want to have scripts only display certain properties if certain conditions are met. If a VM only has one disk for example, instead of ‘Disk 2’ showing as a property, but not showing any data, I don’t want ‘Disk 2’ to show up at all. Then of course if a VM has a “Disk 2”, it will show “Disk 2” in the report, and show data for it.

$count = [int]1

$object = [PSCustomObject][ordered]@{
“Name” = “VM123”
“Disk 2” = $(if ($count.count -gt 1) { something })
}

Since $count.count is not greater than 1, is there a way to eliminate ‘Disk 2’ from showing?

SB,

That’s going to be pretty hard to do and not really ideal. You are create a Key/Value pair and using this as a Property. The key is Disk2, when you call the object it will display all members of the object. You can select which properties to present via the Select-Object VM, Disk1, Disk2. However, if you are running this against multiple VM’s then this wouldn’t work because VM1 may have only 1 disk, but VM2 and VM3 have 2 disks. Instead you would be looking to create an array inside the hashtable instead. Please provide further code for review.

 

There’s always a way … :wink:

[int]$count = 2

Mandatory props

$Props = @{
Name = “VM123”
Size = 1024
Age = 200
}

Conditional props

if ($count -gt 1) {
$Props[‘Disk2’] = ‘Something’
}

$object = New-Object PSObject -Property $Props

$object


… and I’m pretty sure that’s not even the most sophisticated one … :wink:

@Olaf,

That is true, you can do this, but without having the full picture of the script, I don’t think this is effective. Based on the data that is provided it seems SB is trying to compile a report to be used. Only adding the property for select vms doesn’t make a lot of sense to me when we can just query the data and then filter based on Disk2 not equal to null i.e:

$Data | Where-object {$_.Disk2 -ne $null}

 

You can use Add-Member to add an unknown count of properties to an object as in:

$DiskList = @(
    [PSCustomObject]@{ DriveLetter = 'c'; SizeGB=100 }
    [PSCustomObject]@{ DriveLetter = 'd'; SizeGB=200 }
    [PSCustomObject]@{ DriveLetter = 'e'; SizeGB=300 }
)

$myVMObject = [PSCustomObject]@{
    VMName = $env:COMPUTERNAME
    RAMGB  = [Math]::Round((Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory/1GB,0)
    OS     = (Get-WmiObject -Class Win32_OperatingSystem).Caption
}
$DiskList | foreach {
    $myVMObject | Add-Member -MemberType NoteProperty -Name "Drive($($_.DriveLetter))-SizeGB" -Value $_.SizeGB
}

$myVMObject | FL

You’ll get output like:

VMName          : My-PC
RAMGB           : 16
OS              : Microsoft Windows 10 Enterprise 
Drive(c)-SizeGB : 100
Drive(d)-SizeGB : 200
Drive(e)-SizeGB : 300

Notice that the disk property names and count will vary depending on the $DiskList array

To me, it depends on whether you are trying to store these objects together or just spit them out as totally separate outputs. Most of the time, it makes more sense to output an array of objects, all with the same properties. That’s a lot more versatile, and it allows you to do things like piping the output to some other function.

So that would leave me with a couple of options:

  1. Create all of the objects with same properties and just accept that some are going to have empty values for some VMs
  2. Create all of the objects with a DiskDrives property that is an array of the disks
I would lean more towards #2, in this case, because a VM can have a (virtually) unlimited number of disks, so unless you know the max number of disks on each of your machines, there's no way to create a PSObject to handle that.
$Computers = "VM1", "VM2", "VM3"
$Computers | ForEach-Object {
$VM = Get-VM $ComputerName

$disks = $VM | Get-HardDisk | Select-Object Filename, CapacityGB

New-Object -TypeName PSObject -Property @{
“Name”=$VM.Name
“VMHost”=$VM.Host<
“DiskDrives”=$disks
}
}

Would give you something like:
Name VMHost DiskDrives
VM1 ESX20 {"disk1", "disk2"}
VM2 ESX15 {"disk1"}
VM3 ESX42 {"disk1", "disk2", "disk3", "disk4"}
It's pretty basic and ugly because i'm not somewhere I can get real data to look at...

Thank you for the responses. The script is an Azure report, with predefined fields.

[PScustomObject][ordered]@{
“ResourceGroupName” = $vm.resourceGroupName
“VMname” = $vm.Name
“VMsize” = $vm.HardwareProfile.VmSize
“OS Disk name” = $vm.StorageProfile.OSDisk.Name
“Data Disk 0” = $vm.StorageProfile.DataDisks[0].Name
}

So in my example, if a VM doesn’t have any data disks, instead of that field just being blank for a particular VM when the report runs, I was wondering if the ‘Data Disk 0’, and subsequently “Data Disk 1”, and so on, if they could just not show up if a VM doesn’t have any data disks. I was just wondering if it were possible.

So for the report, there will always be a ResourceGroupName, and a VM name, but when it gets to Data Disk 0, it will only show for VMs that have that field.

Again, thank you all for the responses.

Thanks, I’ll keep doing it the way that I have, if the VM doesn’t have any more than 1 disk, that property will just appear blank on the report. I was just curious if it was possible.

 

Thanks again for all of the replies.