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]

Viewing 5 reply threads
  • 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: 115
      Points: 433
      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: 1635
      Points: 3,089
      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: 115
      Points: 433
      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: 427
      Points: 706
      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: 108
      Points: 302
      Helping Hand
      Rank: Contributor

      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.

Viewing 5 reply threads
  • The topic ‘Only show property if a condition is met on [PScustomObject]’ is closed to new replies.