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

Welcome Forums General PowerShell Q&A Only show property if a condition is met on [PScustomObject]

This topic contains 7 replies, has 5 voices, and was last updated by

 
Participant
1 week, 4 days ago.

  • Author
    Posts
  • #174655

    Participant
    Topics: 4
    Replies: 9
    Points: 39
    Rank: Member

    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?

  • #174658

    Participant
    Topics: 0
    Replies: 100
    Points: 363
    Helping Hand
    Rank: Contributor

    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.

     

  • #174673

    Participant
    Topics: 1
    Replies: 1529
    Points: 2,587
    Helping Hand
    Rank: Community Hero

    There's always a way ... 😉

    [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 ... 😉

  • #174676

    Participant
    Topics: 0
    Replies: 100
    Points: 363
    Helping Hand
    Rank: Contributor

    @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}

     

    • #175480

      Participant
      Topics: 4
      Replies: 9
      Points: 39
      Rank: Member

      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.

  • #174703

    Participant
    Topics: 9
    Replies: 423
    Points: 676
    Helping Hand
    Rank: Major Contributor

    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

  • #174874

    Participant
    Topics: 6
    Replies: 78
    Points: 143
    Helping Hand
    Rank: Participant

    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...

    • #175537

      Participant
      Topics: 4
      Replies: 9
      Points: 39
      Rank: Member

      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.

You must be logged in to reply to this topic.