Public/Get-ServerInventory.ps1
<# .SYNOPSIS Retrieves the inventory data for a server. .DESCRIPTION Retrieves the inventory data for a server. .NOTES This function is pulled directly from the real Microsoft Windows Admin Center PowerShell scripts use rights (according to Microsoft): We grant you a non-exclusive, royalty-free right to use, modify, reproduce, and distribute the scripts provided herein. ANY SCRIPTS PROVIDED BY MICROSOFT ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS OR A PARTICULAR PURPOSE. .ROLE Readers .EXAMPLE # Open an elevated PowerShell Session, import the module, and - PS C:\Users\zeroadmin> Get-ServerInventory #> function Get-ServerInventory { Set-StrictMode -Version 5.0 import-module CimCmdlets <# .SYNOPSIS Converts an arbitrary version string into just 'Major.Minor' .DESCRIPTION To make OS version comparisons we only want to compare the major and minor version. Build number and/os CSD are not interesting. #> function convertOsVersion([string] $osVersion) { try { $version = New-Object Version $osVersion -ErrorAction Stop if ($version -and $version.Major -ne -1 -and $version.Minor -ne -1) { $versionString = "{0}.{1}" -f $version.Major, $version.Minor return New-Object Version $versionString } } catch { # The version string is not in the correct format return $null } } <# .SYNOPSIS Determines if CredSSP is enabled for the current server or client. .DESCRIPTION Check the registry value for the CredSSP enabled state. #> function isCredSSPEnabled() { $CredSsp = Get-Item WSMan:\localhost\Service\Auth\CredSSP -ErrorAction SilentlyContinue if ($CredSSp) { return [System.Convert]::ToBoolean($CredSsp.Value) } return $false } <# .SYNOPSIS Determines if the Hyper-V role is installed for the current server or client. .DESCRIPTION The Hyper-V role is installed when the VMMS service is available. This is much faster then checking Get-WindowsFeature and works on Windows Client SKUs. #> function isHyperVRoleInstalled() { $vmmsService = Get-Service -Name "VMMS" -ErrorAction SilentlyContinue return $vmmsService -and $vmmsService.Name -eq "VMMS" } <# .SYNOPSIS Determines if the Hyper-V PowerShell support module is installed for the current server or client. .DESCRIPTION The Hyper-V PowerShell support module is installed when the modules cmdlets are available. This is much faster then checking Get-WindowsFeature and works on Windows Client SKUs. #> function isHyperVPowerShellSupportInstalled() { # quicker way to find the module existence. it doesn't load the module. return !!(Get-Module -ListAvailable Hyper-V -ErrorAction SilentlyContinue) } <# .SYNOPSIS Determines if Windows Management Framework (WMF) 5.0, or higher, is installed for the current server or client. .DESCRIPTION Windows Admin Center requires WMF 5 so check the registey for WMF version on Windows versions that are less than Windows Server 2016. #> function isWMF5Installed([string] $operatingSystemVersion) { Set-Variable Server2016 -Option Constant -Value (New-Object Version '10.0') # And Windows 10 client SKUs Set-Variable Server2012 -Option Constant -Value (New-Object Version '6.2') $version = convertOsVersion $operatingSystemVersion if ($version -eq $null) { return $false # Since the OS version string is not properly formatted we cannot know the true installed state. } if ($version -ge $Server2016) { # It's okay to assume that 2016 and up comes with WMF 5 or higher installed return $true } else { if ($version -ge $Server2012) { # Windows 2012/2012R2 are supported as long as WMF 5 or higher is installed $registryKey = 'HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine' $registryKeyValue = Get-ItemProperty -Path $registryKey -Name PowerShellVersion -ErrorAction SilentlyContinue if ($registryKeyValue -and ($registryKeyValue.PowerShellVersion.Length -ne 0)) { $installedWmfVersion = [Version]$registryKeyValue.PowerShellVersion if ($installedWmfVersion -ge [Version]'5.0') { return $true } } } } return $false } <# .SYNOPSIS Determines if the current usser is a system administrator of the current server or client. .DESCRIPTION Determines if the current usser is a system administrator of the current server or client. #> function isUserAnAdministrator() { return ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") } <# .SYNOPSIS Determines if the current server supports Failover Clusters Time Series Database. .DESCRIPTION Use the existance of the cluster cmdlet Get-ClusterPerformanceHistory to determine if TSDB is supported or not. #> function getClusterPerformanceHistoryCmdLet($failoverClusters) { return $failoverClusters.ExportedCommands.ContainsKey("Get-ClusterPerformanceHistory") } <# .SYNOPSIS Get some basic information about the Failover Cluster that is running on this server. .DESCRIPTION Create a basic inventory of the Failover Cluster that may be running in this server. #> function getClusterInformation() { # JEA code requires to pre-import the module (this is slow on failover cluster environment.) Import-Module FailoverClusters -ErrorAction SilentlyContinue $returnValues = @{} $returnValues.IsTsdbEnabled = $false $returnValues.IsCluster = $false $returnValues.ClusterFqdn = $null $failoverClusters = Get-Module FailoverClusters -ErrorAction SilentlyContinue if ($failoverClusters) { $returnValues.IsTsdbEnabled = getClusterPerformanceHistoryCmdLet $failoverClusters } $namespace = Get-CimInstance -Namespace root/MSCluster -ClassName __NAMESPACE -ErrorAction SilentlyContinue if ($namespace) { $cluster = Get-CimInstance -Namespace root/MSCluster -Query "Select fqdn from MSCluster_Cluster" -ErrorAction SilentlyContinue if ($cluster) { $returnValues.IsCluster = $true $returnValues.ClusterFqdn = $cluster.fqdn } } return $returnValues } <# .SYNOPSIS Get the Fully Qaulified Domain (DNS domain) Name (FQDN) of the passed in computer name. .DESCRIPTION Get the Fully Qaulified Domain (DNS domain) Name (FQDN) of the passed in computer name. #> function getComputerFqdn($computerName) { return ([System.Net.Dns]::GetHostEntry($computerName)).HostName } <# .SYNOPSIS Get the Fully Qaulified Domain (DNS domain) Name (FQDN) of the current server or client. .DESCRIPTION Get the Fully Qaulified Domain (DNS domain) Name (FQDN) of the current server or client. #> function getHostFqdn($computerSystem) { $computerName = $computerSystem.DNSHostName if ($computerName -eq $null) { $computerName = $computerSystem.Name } return getComputerFqdn $computerName } <# .SYNOPSIS Are the needed management CIM interfaces available on the current server or client. .DESCRIPTION Check for the presence of the required server management CIM interfaces. #> function getManagementToolsSupportInformation() { $returnValues = @{} $returnValues.ManagementToolsAvailable = $false $returnValues.ServerManagerAvailable = $false $namespaces = Get-CimInstance -Namespace root/microsoft/windows -ClassName __NAMESPACE -ErrorAction SilentlyContinue if ($namespaces) { $returnValues.ManagementToolsAvailable = ($namespaces | Where-Object { $_.Name -ieq "ManagementTools" }) -ne $null $returnValues.ServerManagerAvailable = ($namespaces | Where-Object { $_.Name -ieq "ServerManager" }) -ne $null } return $returnValues } <# .SYNOPSIS Check the remote app enabled or not. .DESCRIPTION Check the remote app enabled or not. #> function isRemoteAppEnabled() { Set-Variable key -Option Constant -Value "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server" Set-Variable enableRemoteAppPropertyName -Option Constant -Value "EnableRemoteApp" $registryKeyValue = Get-ItemProperty -Path $key -Name EnableRemoteApp -ErrorAction SilentlyContinue return $registryKeyValue -and ($registryKeyValue.PSObject.Properties.Name -match $enableRemoteAppPropertyName) } <# .SYNOPSIS Check the remote app enabled or not. .DESCRIPTION Check the remote app enabled or not. #> <# .SYNOPSIS Get the Win32_OperatingSystem information .DESCRIPTION Get the Win32_OperatingSystem instance and filter the results to just the required properties. This filtering will make the response payload much smaller. #> function getOperatingSystemInfo() { return Get-CimInstance Win32_OperatingSystem | Microsoft.PowerShell.Utility\Select-Object csName, Caption, OperatingSystemSKU, Version, ProductType } <# .SYNOPSIS Get the Win32_ComputerSystem information .DESCRIPTION Get the Win32_ComputerSystem instance and filter the results to just the required properties. This filtering will make the response payload much smaller. #> function getComputerSystemInfo() { return Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue | ` Microsoft.PowerShell.Utility\Select-Object TotalPhysicalMemory, DomainRole, Manufacturer, Model, NumberOfLogicalProcessors, Domain, Workgroup, DNSHostName, Name, PartOfDomain } ########################################################################### # main() ########################################################################### $operatingSystem = getOperatingSystemInfo $computerSystem = getComputerSystemInfo $isAdministrator = isUserAnAdministrator $fqdn = getHostFqdn $computerSystem $managementToolsInformation = getManagementToolsSupportInformation $isWmfInstalled = isWMF5Installed $operatingSystem.Version $clusterInformation = getClusterInformation -ErrorAction SilentlyContinue $isHyperVPowershellInstalled = isHyperVPowerShellSupportInstalled $isHyperVRoleInstalled = isHyperVRoleInstalled $isCredSSPEnabled = isCredSSPEnabled $isRemoteAppEnabled = isRemoteAppEnabled $result = New-Object PSObject $result | Add-Member -MemberType NoteProperty -Name 'IsAdministrator' -Value $isAdministrator $result | Add-Member -MemberType NoteProperty -Name 'OperatingSystem' -Value $operatingSystem $result | Add-Member -MemberType NoteProperty -Name 'ComputerSystem' -Value $computerSystem $result | Add-Member -MemberType NoteProperty -Name 'Fqdn' -Value $fqdn $result | Add-Member -MemberType NoteProperty -Name 'IsManagementToolsAvailable' -Value $managementToolsInformation.ManagementToolsAvailable $result | Add-Member -MemberType NoteProperty -Name 'IsServerManagerAvailable' -Value $managementToolsInformation.ServerManagerAvailable $result | Add-Member -MemberType NoteProperty -Name 'IsCluster' -Value $clusterInformation.IsCluster $result | Add-Member -MemberType NoteProperty -Name 'ClusterFqdn' -Value $clusterInformation.ClusterFqdn $result | Add-Member -MemberType NoteProperty -Name 'IsWmfInstalled' -Value $isWmfInstalled $result | Add-Member -MemberType NoteProperty -Name 'IsTsdbEnabled' -Value $clusterInformation.IsTsdbEnabled $result | Add-Member -MemberType NoteProperty -Name 'IsHyperVRoleInstalled' -Value $isHyperVRoleInstalled $result | Add-Member -MemberType NoteProperty -Name 'IsHyperVPowershellInstalled' -Value $isHyperVPowershellInstalled $result | Add-Member -MemberType NoteProperty -Name 'IsCredSSPEnabled' -Value $isCredSSPEnabled $result | Add-Member -MemberType NoteProperty -Name 'isRemoteAppEnabled' -Value $isRemoteAppEnabled $result } # SIG # Begin signature block # MIIMiAYJKoZIhvcNAQcCoIIMeTCCDHUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUvrEVZXjLCBpBVzL2FxOgvDrZ # 5nqgggn9MIIEJjCCAw6gAwIBAgITawAAAB/Nnq77QGja+wAAAAAAHzANBgkqhkiG # 9w0BAQsFADAwMQwwCgYDVQQGEwNMQUIxDTALBgNVBAoTBFpFUk8xETAPBgNVBAMT # CFplcm9EQzAxMB4XDTE3MDkyMDIxMDM1OFoXDTE5MDkyMDIxMTM1OFowPTETMBEG # CgmSJomT8ixkARkWA0xBQjEUMBIGCgmSJomT8ixkARkWBFpFUk8xEDAOBgNVBAMT # B1plcm9TQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCwqv+ROc1 # bpJmKx+8rPUUfT3kPSUYeDxY8GXU2RrWcL5TSZ6AVJsvNpj+7d94OEmPZate7h4d # gJnhCSyh2/3v0BHBdgPzLcveLpxPiSWpTnqSWlLUW2NMFRRojZRscdA+e+9QotOB # aZmnLDrlePQe5W7S1CxbVu+W0H5/ukte5h6gsKa0ktNJ6X9nOPiGBMn1LcZV/Ksl # lUyuTc7KKYydYjbSSv2rQ4qmZCQHqxyNWVub1IiEP7ClqCYqeCdsTtfw4Y3WKxDI # JaPmWzlHNs0nkEjvnAJhsRdLFbvY5C2KJIenxR0gA79U8Xd6+cZanrBUNbUC8GCN # wYkYp4A4Jx+9AgMBAAGjggEqMIIBJjASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsG # AQQBgjcVAgQWBBQ/0jsn2LS8aZiDw0omqt9+KWpj3DAdBgNVHQ4EFgQUicLX4r2C # Kn0Zf5NYut8n7bkyhf4wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDgYDVR0P # AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUdpW6phL2RQNF # 7AZBgQV4tgr7OE0wMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL3BraS9jZXJ0ZGF0 # YS9aZXJvREMwMS5jcmwwPAYIKwYBBQUHAQEEMDAuMCwGCCsGAQUFBzAChiBodHRw # Oi8vcGtpL2NlcnRkYXRhL1plcm9EQzAxLmNydDANBgkqhkiG9w0BAQsFAAOCAQEA # tyX7aHk8vUM2WTQKINtrHKJJi29HaxhPaHrNZ0c32H70YZoFFaryM0GMowEaDbj0 # a3ShBuQWfW7bD7Z4DmNc5Q6cp7JeDKSZHwe5JWFGrl7DlSFSab/+a0GQgtG05dXW # YVQsrwgfTDRXkmpLQxvSxAbxKiGrnuS+kaYmzRVDYWSZHwHFNgxeZ/La9/8FdCir # MXdJEAGzG+9TwO9JvJSyoGTzu7n93IQp6QteRlaYVemd5/fYqBhtskk1zDiv9edk # mHHpRWf9Xo94ZPEy7BqmDuixm4LdmmzIcFWqGGMo51hvzz0EaE8K5HuNvNaUB/hq # MTOIB5145K8bFOoKHO4LkTCCBc8wggS3oAMCAQICE1gAAAH5oOvjAv3166MAAQAA # AfkwDQYJKoZIhvcNAQELBQAwPTETMBEGCgmSJomT8ixkARkWA0xBQjEUMBIGCgmS # JomT8ixkARkWBFpFUk8xEDAOBgNVBAMTB1plcm9TQ0EwHhcNMTcwOTIwMjE0MTIy # WhcNMTkwOTIwMjExMzU4WjBpMQswCQYDVQQGEwJVUzELMAkGA1UECBMCUEExFTAT # BgNVBAcTDFBoaWxhZGVscGhpYTEVMBMGA1UEChMMRGlNYWdnaW8gSW5jMQswCQYD # VQQLEwJJVDESMBAGA1UEAxMJWmVyb0NvZGUyMIIBIjANBgkqhkiG9w0BAQEFAAOC # AQ8AMIIBCgKCAQEAxX0+4yas6xfiaNVVVZJB2aRK+gS3iEMLx8wMF3kLJYLJyR+l # rcGF/x3gMxcvkKJQouLuChjh2+i7Ra1aO37ch3X3KDMZIoWrSzbbvqdBlwax7Gsm # BdLH9HZimSMCVgux0IfkClvnOlrc7Wpv1jqgvseRku5YKnNm1JD+91JDp/hBWRxR # 3Qg2OR667FJd1Q/5FWwAdrzoQbFUuvAyeVl7TNW0n1XUHRgq9+ZYawb+fxl1ruTj # 3MoktaLVzFKWqeHPKvgUTTnXvEbLh9RzX1eApZfTJmnUjBcl1tCQbSzLYkfJlJO6 # eRUHZwojUK+TkidfklU2SpgvyJm2DhCtssFWiQIDAQABo4ICmjCCApYwDgYDVR0P # AQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBS5d2bhatXq # eUDFo9KltQWHthbPKzAfBgNVHSMEGDAWgBSJwtfivYIqfRl/k1i63yftuTKF/jCB # 6QYDVR0fBIHhMIHeMIHboIHYoIHVhoGubGRhcDovLy9DTj1aZXJvU0NBKDEpLENO # PVplcm9TQ0EsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNl # cnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9emVybyxEQz1sYWI/Y2VydGlmaWNh # dGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlv # blBvaW50hiJodHRwOi8vcGtpL2NlcnRkYXRhL1plcm9TQ0EoMSkuY3JsMIHmBggr # BgEFBQcBAQSB2TCB1jCBowYIKwYBBQUHMAKGgZZsZGFwOi8vL0NOPVplcm9TQ0Es # Q049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENO # PUNvbmZpZ3VyYXRpb24sREM9emVybyxEQz1sYWI/Y0FDZXJ0aWZpY2F0ZT9iYXNl # P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwLgYIKwYBBQUHMAKG # Imh0dHA6Ly9wa2kvY2VydGRhdGEvWmVyb1NDQSgxKS5jcnQwPQYJKwYBBAGCNxUH # BDAwLgYmKwYBBAGCNxUIg7j0P4Sb8nmD8Y84g7C3MobRzXiBJ6HzzB+P2VUCAWQC # AQUwGwYJKwYBBAGCNxUKBA4wDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOC # AQEAszRRF+YTPhd9UbkJZy/pZQIqTjpXLpbhxWzs1ECTwtIbJPiI4dhAVAjrzkGj # DyXYWmpnNsyk19qE82AX75G9FLESfHbtesUXnrhbnsov4/D/qmXk/1KD9CE0lQHF # Lu2DvOsdf2mp2pjdeBgKMRuy4cZ0VCc/myO7uy7dq0CvVdXRsQC6Fqtr7yob9NbE # OdUYDBAGrt5ZAkw5YeL8H9E3JLGXtE7ir3ksT6Ki1mont2epJfHkO5JkmOI6XVtg # anuOGbo62885BOiXLu5+H2Fg+8ueTP40zFhfLh3e3Kj6Lm/NdovqqTBAsk04tFW9 # Hp4gWfVc0gTDwok3rHOrfIY35TGCAfUwggHxAgEBMFQwPTETMBEGCgmSJomT8ixk # ARkWA0xBQjEUMBIGCgmSJomT8ixkARkWBFpFUk8xEDAOBgNVBAMTB1plcm9TQ0EC # E1gAAAH5oOvjAv3166MAAQAAAfkwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwx # CjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGC # NwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFGOcOfhvVQc/E0cT # v4Hvu6xrudh9MA0GCSqGSIb3DQEBAQUABIIBAJbuWK6uTJOJxeE8Hyjtk9xjsKhE # n0QEVm6Wq3+d5DVTZSnFz5u9Oa9LDOzaM0XQyKzHPLPGQk25PcNxnjE+XgnZgp8f # tpTLSZR7zm+M9RUV622pUREOZnpvMsqjUQiyS+frOBwZUbBu8t3pN4FI/6tPUKNA # 6BZ8WSsIL4rQaP7I6gr72Df48DKEV/EqmkH8Pnpiip5rMUwBuiY3j58GvGDkxUH7 # vSKuAO+FuDbTYOSuDlJsC407nIGXn55Sk8T/XE81gTpn2fbFYgP2pE72ZLR28PAi # BaYk9CQCh0IdhQgJwUq/Wte2NXEArByfHH9eAv+YlGZPNfjl9lKCrJGpv2I= # SIG # End signature block |