Daybreak Faction - code beauty at it's best - Puzzle 2

This topic contains 11 replies, has 5 voices, and was last updated by  Alex Aymonier 3 weeks, 1 day ago.

  • Author
    Posts
  • #91910

    Alex Aymonier
    Participant

    Go

  • #91991

    JB Lewis
    Participant

    Here goes!

    Based on the premise that a function should output one type of object, I opted to deliver the collection of disk objects as the value of a Disks property.

    #SaveThePuppies!

    function Get-ComputerAndDiskInfo
    {
        [CmdletBinding()]
        param(
            [String[]]
            $Computername = $env:COMPUTERNAME
        )
    
        process
        {
            foreach ($Computer in $Computername)
            {
                $Disks = Get-CimInstance Win32_LogicalDisk -ComputerName $Computer 
    
                # Iterate to get the labels correct
                $DiskInfo = foreach ($Disk in $Disks) 
                {
                    Try
                    {
                        $DiskPctFreeSpace = [math]::Round(($Disk.FreeSpace / $Disk.Size) * 100, 2)
                        $DiskPctUsedSpace = 100 - $DiskPctFreeSpace
                    }
                    Catch 
                    {
                        $DiskPctUsedSpace = $null
                    }
                    
                    [PSCustomObject]@{
                        PSTypeName    = "IronScripter.DayBreak.DiskInfoItem"
                        "Drive"       = $Disk.DeviceID
                        "DriveType"   = $Disk.Description
                        "Size"        = $Disk.Size
                        "FreeSpace"   = $Disk.FreeSpace
                        "PercentUsed" = $DiskPctUsedSpace
                        "Compressed"  = $Disk.Compressed
                    }
                }
    
                $OperatingSystem = Get-CimInstance Win32_OperatingSystem -ComputerName $Computer
    
                $ServicePack = $OperatingSystem.ServicePackMajorVersion, $OperatingSystem.ServicePackMinorVersion -join "."
    
                $AllInfo = [pscustomobject]@{
                    PSTypeName                  = "IronScripter.DayBreak.ComputerInfoItem"
                    "OS Name"                   = $OperatingSystem.Caption
                    "Version"                   = $OperatingSystem.Version
                    "Service Pack"              = $ServicePack
                    "OS Manufacturer"           = $OperatingSystem.Manufacturer
                    "Windows Directory"         = $OperatingSystem.WindowsDirectory
                    "Locale"                    = $OperatingSystem.Locale
                    "Available Physical Memory" = $OperatingSystem.FreePhysicalMemory
                    "Total Virtual Memory"      = $OperatingSystem.TotalVirtualMemorySize
                    "Available Virtual Memory"  = $OperatingSystem.FreeVirtualMemory
                    "Disks"                     = $DiskInfo
                }
                $AllInfo
            }
        }
    }
    

    (Edit)I still need to come up with a format.ps1xml (see below), but the core is there. It's better than "Battle", but how much more do I polish before it becomes "flawless"?

  • #92003

    JB Lewis
    Participant

    Apparently I need to more closely read ALL of the puzzle description!

    I can count on my left thumb the number of times I've written a format.ps1xml

  • #92017

    Alex Aymonier
    Participant

    Function is done (I think) have tested on local laptop and 2 servers. So far so good. Just need to create the format file to go with the function

    $AALogPreference = "c:\Get-ComputerInfoErrors.txt"
    Function Get-ComputerInformation {
    
        [CmdletBinding()]
        [OutputType('PSCustomObject')]
    
        Param 
        (
            [Parameter(Mandatory=$false, 
                       ValueFromPipeline=$true,
                       ValueFromPipelineByPropertyName=$true, 
                       HelpMessage="The Computer Name.", 
                       Position=0)]
            [ValidateNotNull()]
            [ValidateNotNullOrEmpty()]
            [Alias('name')]
            [SupportsWildcards()]
            [string[]]$ComputerName = $env:COMPUTERNAME,
    
            [Parameter()]
            [string]$ErrorLogFilePath = $AALogPreference
    
        )
    
        Begin
        {
    
            Remove-Item -Path $ErrorLogFilePath -Force -ErrorAction SilentlyContinue
            $ErrorsHappened = $False
    
        }
        Process
        {
    
            foreach ($computer in $ComputerName) {
    
                Try{
                    Write-Verbose -Message "Attempting to connect to $computer"
                    $OperatingSystem = Get-CimInstance -ComputerName $computer -Namespace 'ROOT/cimv2'  -ClassName 'Win32_OperatingSystem' -ErrorAction Stop
                    $Locale          = ([System.Globalization.CultureInfo]([int]("0x" + $OperatingSystem.Locale))).name
                    $Disks           = Get-CimInstance -ComputerName $computer -Namespace 'ROOT/cimv2'  -ClassName 'Win32_LogicalDisk' 
                    $DisksTotal      = $($Disks.count)
    
                    $PSObject = New-Object PSObject -Property ([ordered]@{
    
                                'Computername'              = $computer
                                'Status'                    = 'Connected'
                                'OS Name'                   = $OperatingSystem.Caption
                                'Version'                   = $OperatingSystem.Version
                                'Service Pack'              = -join ("$($OperatingSystem.ServicePackMajorVersion)",
                                                                     ".",
                                                                     "$($OperatingSystem.ServicePackMinorVersion)")
                                'OS Manufacturer'           = $OperatingSystem.Manufacturer
                                'Windows Directory'         = $OperatingSystem.WindowsDirectory
                                'Locale'                    = $locale.Name
                                'Available Physical Memory' = $OperatingSystem.FreePhysicalMemory
                                'Total Virtual Memory'      = $OperatingSystem.TotalVirtualMemorySize
                                'Available Virtual Memory'  = $OperatingSystem.FreeVirtualMemory
                    
                    }) #End $PSObject
    
                    For ($i = 0; $i -lt $DisksTotal; $i++) {
    
                        $PSObject | Add-Member -MemberType NoteProperty -Name "Drive($i)"       -Value $Disks[$i].DeviceID
                        $PSObject | Add-Member -MemberType NoteProperty -Name "DriveType($i)"   -Value $Disks[$i].Description
                        $PSObject | Add-Member -MemberType NoteProperty -Name "SizeGB($i)"      -Value ($Disks[$i].Size/1GB).ToString('0.00')
                        $PSObject | Add-Member -MemberType NoteProperty -Name "FreeSpaceGB($i)" -Value ($Disks[$i].FreeSpace/1GB).ToString('0.00')
                        $PSObject | Add-Member -MemberType NoteProperty -Name "Compressed($i)"  -Value $Disks[$i].Compressed
                        If (-not($Disks[$i].Size)) {
                            $PSObject | Add-Member -MemberType NoteProperty -Name "PercentUsedSpace($i)" -Value $null
                        }else{
                            $PSObject | Add-Member -MemberType NoteProperty -Name "PercentUsedSpace($i)" -Value (1 - ([Int64]$Disks[$i].FreeSpace/[Int64]$Disks[$i].Size)).ToString("P")
                        }
                        
                    } #End For
    
                } Catch {
                    Write-Error -Message "Errors hapened when attempting to find data for $computer"
                    $ErrorsHappened = $True
    
                    $PSObject = New-Object PSObject -Property ([ordered]@{
    
                                'Computername'              = $computer
                                'Status'                    = 'Disconnected'
                                'OS Name'                   = $null
                                'Version'                   = $null
                                'Service Pack'              = $null
                                'OS Manufacturer'           = $null
                                'Windows Directory'         = $null
                                'Locale'                    = $null
                                'Available Physical Memory' = $null
                                'Total Virtual Memory'      = $null
                                'Available Virtual Memory'  = $null
            
                    }) #End $PSObject
    
                    For ($i = 0; $i -lt $DisksTotal; $i++) {
    
                        $PSObject | Add-Member -MemberType NoteProperty -Name "Drive($i)"            -Value $null
                        $PSObject | Add-Member -MemberType NoteProperty -Name "DriveType($i)"        -Value $null
                        $PSObject | Add-Member -MemberType NoteProperty -Name "SizeGB($i)"           -Value $null
                        $PSObject | Add-Member -MemberType NoteProperty -Name "FreeSpaceGB($i)"      -Value $null
                        $PSObject | Add-Member -MemberType NoteProperty -Name "PercentUsedSpace($i)" -Value $null
                        $PSObject | Add-Member -MemberType NoteProperty -Name "Compressed($i)"       -Value $null
                        
                    } #End For
    
                    $computer | Out-File -FilePath $ErrorLogFilePath -Append
                } Finally {
    
                    $PSObject.psobject.typenames.insert(0,'Alex.Object.Type')
                    Write-Output $PSObject
    
                }
    
            } #End Foreach
        }
        End
        {
            if ($ErrorsHappened) {
    
                Write-Warning "Errors happened and are logged to $ErrorLogFilePath."
            
            }
        }
    
    }
    
    • #92018

      Alex Aymonier
      Participant

      Would love to know if this is the best way to deal with the multiple disk.

    • #92159

      Alex Aymonier
      Participant

      Here is the formats file

    • #92179

      Alex Aymonier
      Participant

      Just been thinking more on this and I'm not getting a total number of disks for all machines so the object size will be whatever the 1st machine total disks is. Thats all well and good untill the 1st machine has a c and d drive and the next one has c, d and e. Won't work with export-csv and format-table etc. Back to the drawing board.

  • #92021

    John Steele
    Participant

    Trying to figure out how to implement the multiple disk situation is definitely where I spent most of my time on this. I went back and forth but ultimately ended up on this solution. I created a hash table for all the computer stats and then added the disk stats to the hash table for each disk in the loop. I used the drive letter to identify each property. I still need to add the custom view to pretty this up but it's coming soon.

  • #92168

    Brandon Olin
    Participant

    Here is mine.

  • #92267

    Josh Rickard
    Participant

    So, I like everyone's code so far! I took a little different route, hope you all don't mind.

    # Define a class
    class SystemInformation
    {
        [string]$Drive
        [string]$DriveType
        [string]$Size
        [string]$FreeSpace
        [string]$PercentFree
        [string]$Compressed
    
        [string]$OSName
        [string]$Version
        [string]$ServicePack
        [string]$OSManufacturer
        [string]$WindowsDirectory
        [string]$Locale
        [string]$FreePhysicalMemory
        [string]$TotalPhsicalMemory
        [string]$TotalVirtualMemory
        [string]$FreeVirtualMemory
    
       # Constructor
       SystemInformation ()
       {
            $this.getOperatingSystemInformation()
            $this.getDisks()
       }
    
        getDisks()
        {
            $disks = Get-WmiObject -Query "SELECT * FROM Win32_LogicalDisk"
    
            $disks
            foreach($disk in $disks) {
                    $this.Drive       = $disk.DeviceID
                    $this.DriveType   = $disk.Description
                    $this.Size        = $disk.Size
                    $this.FreeSpace   = $disk.FreeSpace
                    $this.PercentFree = "$([Math]::Round(($disk.FreeSpace / $disk.Size * 100),0))%"
                    $this.Compressed  = $disk.Compressed
            }
        }
    
        getOperatingSystemInformation()
        {
            
            $osObject =Get-WmiObject -Query "SELECT * FROM Win32_OperatingSystem"
                $this.OSName             = $osObject.Name
                $this.Version            = $osObject.Version
                $this.ServicePack        = "$($osObject.ServicePackMajorVersion).$($osObject.ServicePackMinorVersion)"
                $this.OSManufacturer     = $osObject.Manufacturer
                $this.WindowsDirectory   = $osObject.WindowsDirectory
                $this.Locale             = $osObject.Locale
                $this.FreePhysicalMemory = $([math]::Round($osObject.FreePhysicalMemory/1mb, 2))
                $this.TotalPhsicalMemory = (Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)})
                $this.TotalVirtualMemory = $([math]::Round($osObject.TotalVirtualMemorySize/1mb, 2))
                $this.FreeVirtualMemory  = $([math]::Round($osObject.FreeVirtualMemory/1mb, 2))
       }
    }
    

    Thanks,

  • #92269

    Josh Rickard
    Participant

    Well, crap. I submitted a post but it seems to have disappeared. Here is my take on this one. I hope you all enjoy it:

    # Define a class
    class SystemInformation
    {
        [string]$Drive
        [string]$DriveType
        [string]$Size
        [string]$FreeSpace
        [string]$PercentFree
        [string]$Compressed
    
        [string]$OSName
        [string]$Version
        [string]$ServicePack
        [string]$OSManufacturer
        [string]$WindowsDirectory
        [string]$Locale
        [string]$FreePhysicalMemory
        [string]$TotalPhsicalMemory
        [string]$TotalVirtualMemory
        [string]$FreeVirtualMemory
    
       # Constructor
       SystemInformation ()
       {
            $this.getOperatingSystemInformation()
            $this.getDisks()
       }
    
        getDisks()
        {
            $disks = Get-WmiObject -Query "SELECT * FROM Win32_LogicalDisk"
    
            $disks
            foreach($disk in $disks) {
                    $this.Drive       = $disk.DeviceID
                    $this.DriveType   = $disk.Description
                    $this.Size        = $disk.Size
                    $this.FreeSpace   = $disk.FreeSpace
                    $this.PercentFree = "$([Math]::Round(($disk.FreeSpace / $disk.Size * 100),0))%"
                    $this.Compressed  = $disk.Compressed
            }
        }
    
        getOperatingSystemInformation()
        {
            
            $osObject =Get-WmiObject -Query "SELECT * FROM Win32_OperatingSystem"
                $this.OSName             = $osObject.Name
                $this.Version            = $osObject.Version
                $this.ServicePack        = "$($osObject.ServicePackMajorVersion).$($osObject.ServicePackMinorVersion)"
                $this.OSManufacturer     = $osObject.Manufacturer
                $this.WindowsDirectory   = $osObject.WindowsDirectory
                $this.Locale             = $osObject.Locale
                $this.FreePhysicalMemory = $([math]::Round($osObject.FreePhysicalMemory/1mb, 2))
                $this.TotalPhsicalMemory = (Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)})
                $this.TotalVirtualMemory = $([math]::Round($osObject.TotalVirtualMemorySize/1mb, 2))
                $this.FreeVirtualMemory  = $([math]::Round($osObject.FreeVirtualMemory/1mb, 2))
       }
    }

    Would love to hear your feedback! Thanks!

    • #92326

      Alex Aymonier
      Participant

      Good looking code but i've not played with Classes personally so don't know how to use this. Maybe i need to learn classes 🙂

You must be logged in to reply to this topic.