Chapters/graphical-controllers-wpf/TMMachineInfo/TMMachineInfo.psm1

#Requires -version 5.0

class ToolmakingMachineInfo {

    # Properties
    [string]$ComputerName
    [string]$OSVersion
    [string]$SPVersion
    [string]$OSBuild
    [string]$Manufacturer
    [string]$Model
    [int32]$Procs
    [int32]$Cores
    [int32]$RAM
    [int64]$SysDriveFreeSpace
    [string]$Arch
    hidden [string]$Protocol

    # Constructors
    ToolmakingMachineInfo([string]$ComputerName, [string]$Protocol) {
        $this.ComputerName = $ComputerName
        $this.Protocol = $Protocol
        $this.Refresh()
    }

    Refresh() {
        if ($this.protocol -eq 'Dcom') {
            $option = New-CimSessionOption -Protocol Dcom
        } else {
            $option = New-CimSessionOption -Protocol Wsman
        }
 
        Try {
            $params = @{'ComputerName'=$this.Computername
                        'SessionOption'=$option
                        'ErrorAction'='Stop'}
            $session = New-CimSession @params
  
            $os_params = @{'ClassName'='Win32_OperatingSystem'
                           'CimSession'=$session}
            $os = Get-CimInstance @os_params

            $cs_params = @{'ClassName'='Win32_ComputerSystem'
                           'CimSession'=$session}
            $cs = Get-CimInstance @cs_params

            $sysdrive = $os.SystemDrive
            $drive_params = @{'ClassName'='Win32_LogicalDisk'
                              'Filter'="DeviceId='$sysdrive'"
                              'CimSession'=$session}
            $drive = Get-CimInstance @drive_params

            $proc_params = @{'ClassName'='Win32_Processor'
                             'CimSession'=$session}
            $proc = Get-CimInstance @proc_params |
                    Select-Object -first 1

            $session | Remove-CimSession
  
            $this.OSVersion=$os.version
            $this.SPVersion=$os.servicepackmajorversion
            $this.OSBuild=$os.buildnumber
            $this.Manufacturer=$cs.manufacturer
            $this.Model=$cs.model
            $this.Procs=$cs.numberofprocessors
            $this.Cores=$cs.numberoflogicalprocessors
            $this.RAM=($cs.totalphysicalmemory / 1GB)
            $this.Arch=$proc.addresswidth
            $this.SysDriveFreeSpace=$drive.freespace

        } Catch {
            throw "Failed to connect to $this.computername on $this.protocol"
        } #try/catch
    }

} #class

Function Get-MachineInfo {
[cmdletbinding()]
Param(
[Parameter(Position = 0,ValueFromPipeline)]
[Alias("cn")]
[ValidateNotNullorEmpty()]
[string[]]$Computername = $env:COMPUTERNAME,

[ValidateSet("dcom","wsman")]
[string]$Protocol = "wsman"

)

Begin {
    Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"  
} #begin

Process {
    foreach ($computer in $computername) {
        Write-Verbose "[PROCESS] Getting machine information from $($computer.toUpper())"
        New-Object -TypeName ToolMakingMachineInfo -ArgumentList $computer,$protocol

    }

} #process

End {
    Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)"
} #end

}

Function Update-MachineInfo {
[cmdletbinding()]
Param(
[Parameter(Position = 0, ValueFromPipeline)]
[ValidateNotNullorEmpty()]
[ToolmakingMachineInfo]$Info,
[switch]$Passthru
)

Begin {
    Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"  
} #begin


Process {
    Write-Verbose "[PROCESS] Refreshing: $(($Info.ComputerName).ToUpper())"
    $info.Refresh()

    if ($Passthru) {
        #write the updated object back to the pipeline
        $info
    }

} #process

End {
    Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)"
} #end
}

Function Show-MachineInfo {
[cmdletbinding()]
Param(
[Parameter(Position = 0)]
[Alias("cn")]
[ValidateNotNullorEmpty()]
[string]$Computername = $env:COMPUTERNAME,

[ValidateSet("dcom","wsman")]
[string]$Protocol = "wsman"
)

$form = new-object System.Windows.Window
$form.Title = "Machine Info"
$form.Width = 300
$form.Height = 350

$stack = new-object System.Windows.Controls.StackPanel

$txtInput = new-object System.Windows.Controls.TextBox
$txtInput.Width = 100
$txtInput.HorizontalAlignment = "left"
$txtInput.Text = $env:computername

$stack.AddChild($txtInput)

$radioWsman = new-object System.Windows.Controls.RadioButton
$radioWsman.HorizontalAlignment = "Left"
$radioWsman.GroupName = "Protocol"
$radioWsman.Content = "WSMAN"
$radioWsman.IsChecked = $True
$stack.AddChild($radioWsman)

$radioDcom = new-object System.Windows.Controls.RadioButton
$radioDcom.HorizontalAlignment = "Left"
$radioDcom.GroupName = "Protocol"
$radioDcom.Content = "DCOM"
$radioDcom.IsChecked = $False

$stack.AddChild($radioDcom)

$txtResults = new-object System.Windows.Controls.TextBlock
$txtResults.FontFamily = "Consolas"
$txtResults.HorizontalAlignment = "left"

$txtResults.Height = 200

$stack.AddChild($txtResults)

$btnRun = new-object System.Windows.Controls.Button
$btnRun.Content = "_Run"
$btnRun.Width = 60
$btnRun.HorizontalAlignment = "Center"

$OK = {
    #get the selected protocol
    if ($radioWsman.IsChecked) {
        $protocol = "WSMAN"
    }
    else {
        $protocol = "DCOM"
    }
    #get machine info from the name in the text box.
    #we're trimming the value in case there are extra space
    $data = Get-MachineInfo -Computername ($txtInput.text).trim() -Protocol $protocol

    #set the value of the txtResults to the data as a string
    $txtResults.text = $data | Out-String
}

$btnRun.Add_click($OK)

$stack.AddChild($btnRun)

$btnQuit = new-object System.Windows.Controls.Button
$btnQuit.Content = "_Quit"
$btnQuit.Width = 60
$btnQuit.HorizontalAlignment = "center"

$btnQuit.Add_click({$form.close()})

$stack.AddChild($btnQuit)
$form.AddChild($stack)

$form.add_Loaded($ok)

$form.ShowDialog() | Out-null

}


#define command aliases
Set-Alias -Name gmi -Value Get-MachineInfo
Set-Alias -Name umi -Value Update-MachineInfo
set-alias -Name smi -value Show-MachineInfo