Helpers/Launcher/PSRemoting/Get-LauncherPSRemotingWelcome.ps1

<#
    .SYNOPSIS
        Get the core performance counter and system information for the
        PowerShell Remoting launcher welcome screen.
 
    .DESCRIPTION
        This command will use CIM and Performance Counter as well as some other
        command line tools to get the current system summary. The summary will
        be returned as a PowerShell object.
 
    .EXAMPLE
        PS C:\> Get-LauncherPSRemotingWelcome
        Get the system summary of the local system.
 
    .EXAMPLE
        PS C:\> Get-LauncherPSRemotingWelcome -Session $session
        Get the system summary of the system behind the session.
#>

function Get-LauncherPSRemotingWelcome
{
    [CmdletBinding()]
    param
    (
        # Optional session to use for the system summary.
        [Parameter(Mandatory = $false)]
        [AllowNull()]
        [System.Management.Automation.Runspaces.PSSession]
        $Session
    )

    try
    {
        $queryScriptBlock = {

            Set-StrictMode -Version latest

            switch -wildcard ([System.Globalization.CultureInfo]::InstalledUICulture.Name)
            {
                'de-*'
                {
                    $perfProcessorUtilityName = '\Prozessorinformationen(_Total)\Prozessorauslastung'
                    $perfMemoryAvailableName  = '\Arbeitsspeicher\Verfügbare MB'
                }
                default
                {
                    $perfProcessorUtilityName = '\Processor Information(_Total)\% Processor Utility'
                    $perfMemoryAvailableName  = '\Memory\Available MBytes'
                }
            }

            # Gather data from performance counters and CIM system
            $perfCounter        = Get-Counter -Counter $perfProcessorUtilityName, $perfMemoryAvailableName -SampleInterval 1 -MaxSamples 1
            $cimComputerSystem  = Get-CimInstance -ClassName 'Win32_ComputerSystem' -Property 'Name', 'Domain', 'NumberOfProcessors', 'NumberOfLogicalProcessors'
            $cimOperatingSystem = Get-CimInstance -ClassName 'Win32_OperatingSystem' -Property 'Caption', 'Version', 'OSLanguage', 'OSArchitecture', 'LastBootUpTime', 'TotalVisibleMemorySize'
            $cimPageFile        = Get-CimInstance -ClassName 'Win32_PageFileUsage' -Property 'CurrentUsage', 'AllocatedBaseSize'
            $cimDisks           = Get-CimInstance -Namespace 'ROOT/Microsoft/Windows/Storage' -ClassName 'MSFT_Disk' -Property 'Number'
            $cimPartitions      = Get-CimInstance -Namespace 'ROOT/Microsoft/Windows/Storage' -ClassName 'MSFT_Partition' -Property 'DiskNumber', 'PartitionNumber', 'MbrType', 'GptType', 'DriveLetter', 'AccessPaths', 'Size'
            $cimVolumes         = Get-CimInstance -Namespace 'ROOT/Microsoft/Windows/Storage' -ClassName 'MSFT_Volume' -Property 'Path', 'FileSystemLabel', 'Size', 'SizeRemaining'
            $processCount       = (Get-Process).Count
            $connectionCount    = (netstat.exe -n).Count - 4    # Subtract the netstat header

            # Enumerate the sessions
            $sessions = @(@(qwinsta.exe) | Where-Object { $_ -match '(Active|Aktiv)' } | Select-Object @{ N = 'Id'; E = { $_.Substring(41,5).Trim() } }, @{ N = 'User'; E = { $_.Substring(19,22).Trim() } }, @{ N = 'Session'; E = { $_.Substring(1,18).Trim() } })

            $outputDisks = @()
            foreach ($cimDisk in $cimDisks)
            {
                $diskNumber = $cimDisk.Number

                foreach ($cimPartition in ($cimPartitions | Where-Object { $_.DiskNumber -eq $cimDisk.Number }))
                {
                    $partitionNumber = $cimPartition.PartitionNumber

                    $partitionType = 'Unknown'
                    switch ($cimPartition.MbrType)
                    {
                        1   { $partitionType = 'FAT12' }
                        2   { $partitionType = 'Xenix' }
                        3   { $partitionType = 'Xenix' }
                        4   { $partitionType = 'FAT16' }
                        5   { $partitionType = 'Extended' }
                        6   { $partitionType = 'Logical' }
                        7   { $partitionType = 'IFS' }
                        10  { $partitionType = 'OS/2 BootMgr' }
                        11  { $partitionType = 'FAT32' }
                        12  { $partitionType = 'FAT32 XINT13' }
                        14  { $partitionType = 'XINT13' }
                        15  { $partitionType = 'XINT13 Extended' }
                        65  { $partitionType = 'PReP' }
                        66  { $partitionType = 'LDM' }
                        99  { $partitionType = 'Unix' }
                        231 { $partitionType = 'Space Protective' }
                    }
                    switch ($cimPartition.GptType)
                    {
                        '{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}' { $partitionType = 'System' }
                        '{e3c9e316-0b5c-4db8-817d-f92df00215ae}' { $partitionType = 'Reserved' }
                        '{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}' { $partitionType = 'Basic' }
                        '{5808c8aa-7e8f-42e0-85d2-e1e90434cfb3}' { $partitionType = 'LDM Metadata' }
                        '{af9b60a0-1431-4f62-bc68-3311714a69ad}' { $partitionType = 'LDM Data' }
                        '{de94bba4-06d1-4d40-a16a-bfd50179d6ac}' { $partitionType = 'Recovery' }
                        '{e75caf8f-f680-4cee-afa3-b001e56efc2d}' { $partitionType = 'Space Protective' }
                        '{eeff8352-dd2a-44db-ae83-bee1cf7481dc}' { $partitionType = 'S2D Cache' }
                        '{03aaa829-ebfc-4e7e-aac9-c4d76c63b24b}' { $partitionType = 'S2D Cache Metadata' }
                    }

                    $outputDisk = [PSCustomObject] @{
                        Id          = '{0}x{1}' -f $diskNumber, $partitionNumber
                        Label       = $partitionType
                        DriveLetter = $cimPartition.DriveLetter.ToSTring().Trim()
                        AccessPath  = [System.String] ($cimPartition.AccessPaths | Where-Object { $_ -match '^[A-Z]:\\' } | Select-Object -First 1)
                        Size        = $cimPartition.Size
                        Usage       = $null
                        Free        = $null
                        Used        = $null
                        IsSystem    = $cimPartition.DriveLetter -eq 'C'
                    }

                    $volumeNumber = $cimPartition.AccessPaths | Where-Object { $_ -match '^\\\\\?\\Volume{(?<VolumeNumber>[0-9a-fA-F-]{36}})\\$' } | Select-Object -First 1
                    if ($null -ne $volumeNumber)
                    {
                        $cimVolume = $cimVolumes | Where-Object { $_.Path -eq $volumeNumber } | Select-Object -First 1
                        if ($null -ne $cimVolume)
                        {
                            if (-not [System.String]::IsNullOrEmpty($cimVolume.FileSystemLabel))
                            {
                                $outputDisk.Label = $cimVolume.FileSystemLabel
                            }

                            $outputDisk.Size  = $cimVolume.Size
                            $outputDisk.Free  = $cimVolume.SizeRemaining
                            $outputDisk.Used  = $cimVolume.Size - $cimVolume.SizeRemaining
                            if ($cimVolume.Size -gt 0)
                            {
                                $outputDisk.Usage = ($cimVolume.Size - $cimVolume.SizeRemaining) / $cimVolume.Size
                            }
                        }
                    }

                    # if ($null -eq $volumeNumber -or $null -eq $cimVolume)
                    # {
                        # continue
                    # }

                    $outputDisks += $outputDisk
                }
            }

            $output = [PSCustomObject] @{
                Timestamp       = $null
                Hostname        = $cimComputerSystem.Name
                Domain          = $cimComputerSystem.Domain
                PowerShell      = $PSVersionTable.PSVersion
                ComputerSystem  = [PSCustomObject] @{
                    Timestamp       = [System.DateTime]::Now
                    Uptime          = [System.DateTime]::Now - $cimOperatingSystem.LastBootUpTime
                    BootTime        = $cimOperatingSystem.LastBootUpTime
                }
                OperatingSystem = [PSCustomObject] @{
                    Name            = $cimOperatingSystem.Caption.Replace('Microsoft Windows', 'Windows')
                    Version         = $cimOperatingSystem.Version
                    Language        = [System.Globalization.CultureInfo]::new([int] $cimOperatingSystem.OSLanguage).Name
                    Architecture    = $cimOperatingSystem.OSArchitecture
                }
                Processor       = [PSCustomObject] @{
                    SocketCount     = $cimComputerSystem.NumberOfProcessors
                    CoreCount       = $cimComputerSystem.NumberOfLogicalProcessors
                    Load            = $perfCounter.CounterSamples.Where({$_.Path -like "\\*$perfProcessorUtilityName"}).CookedValue * $cimComputerSystem.NumberOfLogicalProcessors / 100
                    Usage           = $perfCounter.CounterSamples.Where({$_.Path -like "\\*$perfProcessorUtilityName"}).CookedValue / 100
                }
                Memory          = [PSCustomObject] @{
                    Size            = $cimOperatingSystem.TotalVisibleMemorySize / 1MB
                    Usage           = (($cimOperatingSystem.TotalVisibleMemorySize / 1KB) - $perfCounter.CounterSamples.Where({$_.Path -like "\\*$perfMemoryAvailableName"}).CookedValue) / ($cimOperatingSystem.TotalVisibleMemorySize / 1KB)
                }
                Page            = [PSCustomObject] @{
                    Size            = $cimPageFile.AllocatedBaseSize / 1KB
                    Usage           = $cimPageFile.CurrentUsage / $cimPageFile.AllocatedBaseSize
                }
                Disks           = $outputDisks
                Processes       = [PSCustomObject] @{
                    Count           = $processCount
                }
                Connections     = [PSCustomObject] @{
                    Count           = $connectionCount
                }
                Sessions        = [PSCustomObject] @{
                    Count           = $sessions.Count
                }
                PSSessions     = [PSCustomObject] @{
                    Count           = @(Get-Process -Name 'pwsh', 'powershell' -ErrorAction 'SilentlyContinue').Count
                }
                WinRMSessions   = [PSCustomObject] @{
                    Count           = @(Get-Process -Name 'wsmprovhost' -ErrorAction 'SilentlyContinue').Count
                }
            }

            # Update the timestamp as the last step
            $output.Timestamp = [System.DateTime]::Now

            Write-Output $output
        }

        if ($PSBoundParameters.ContainsKey('Session') -and $null -ne $Session)
        {
            $output = Invoke-Command -Session $Session -ScriptBlock $queryScriptBlock
        }
        else
        {
            $output = & $queryScriptBlock
        }

        Write-Output $output
    }
    catch
    {
        $PSCmdlet.ThrowTerminatingError($_)
    }
}