function Get-RolesAndFeatures {
<#
.SYNOPSIS
Gets a list of Features / Roles / Role Services on the target server.
.DESCRIPTION
The data returned for each includes name, description, installstate, installed?... Can be called with a FeatureName or FeatureType both of which are optional.
.EXAMPLE
./GetFeaturesAndRoles.ps1
When called with no parameters, returns data for all roles, features and role services available on the server
.EXAMPLE
./GetFeaturesAndRoles.ps1 -FeatureName 'Web-Server'
When called with a FeatureName (e.g. Web-Server) returns details for the given feature if it is available
.EXAMPLE
./GetFeaturesAndRoles.ps1 -FeatureType 'Role'
When called with a FeatureType ('Role', 'Feature' or 'Role Service) returns details for all avilable features of that FeatureType
.NOTES
The supported Operating Systems are Window Server 2012, Windows Server 2012R2, Windows Server 2016.
.ROLE
Readers
#>
param(
[Parameter(Mandatory=$False)]
[string]
$FeatureName = '',
[Parameter(Mandatory=$False)]
[ValidateSet('Role', 'Role Service', 'Feature', IgnoreCase=$False)]
[string]
$FeatureType = ''
)
Import-Module ServerManager
$result = $null
if ($FeatureName) {
$result = Get-WindowsFeature -Name $FeatureName
} else {
if ($FeatureType) {
$result = Get-WindowsFeature | Where-Object { $_.FeatureType -EQ $FeatureType }
} else {
$result = Get-WindowsFeature
}
}
$result
}
## [END] Get-RolesAndFeatures ##
function Install-RolesAndFeatures {
<#
.SYNOPSIS
Installs a Feature/Role/Role Service on the target server.
.DESCRIPTION
Installs a Feature/Role/Role Service on the target server, using Install-WindowsFeature PowerShell cmdlet. Returns a status object
that contains the following properties:
success - true/false depending on if the overall operation Succeeded
status - status message
result - response from Install-WindowsFeature call
.PARAMETER FeatureName
Is a required parameter and is the name of the Role/Feature/Role Service to install
.PARAMETER IncludeAllSubFeature
Is an optional switch parameter that is passed as a similar named parameter to Install-WindowsFeature
.PARAMETER IncludeManagementTools
Is an optional switch parameter that is passed as a similar named parameter to Install-WindowsFeature
.PARAMETER Restart
Is an optional switch parameter that is passed as a similar named parameter to Install-WindowsFeature
.EXAMPLE
./InstallRolesAndFeature.ps1 -FeatureName 'ManagementOData'
Installs the feature 'ManagementObject' without subfeature and management tools
.EXAMPLE
./InstallRolesAndFeature.ps1 -FeatureName 'Web-Server' -IncludeAllSubFeature -IncludeManagementTools
Installs the role 'Web-Server' with all dependencies and management tools
.EXAMPLE
./InstallRolesAndFeature.ps1 -FeatureName 'ManagementOData' -Restart
Installs the feature 'ManagementObject' without subfeature and management tools and reboots the server
.NOTES
The supported Operating Systems are Window Server 2012, Windows Server 2012R2, Windows Server 2016.
.ROLE
Administrators
#>
param(
[Parameter(Mandatory=$True)]
[string[]]
$FeatureName,
[Parameter(Mandatory=$False)]
[Switch]
$IncludeAllSubFeature,
[Parameter(Mandatory=$False)]
[Switch]
$IncludeManagementTools,
[Parameter(Mandatory=$False)]
[Switch]
$Restart,
[Parameter(Mandatory=$False)]
[Switch]
$WhatIf
)
Import-Module ServerManager
Enum InstallStatus {
Failed = 0
Succeeded = 1
NoSuchFeature = 2
AlreadyInstalled = 3
Pending = 4
}
$result = $Null
$status = $Null
$success = $False
$ErrorActionPreference = "Stop"
$feature = Get-WindowsFeature -Name $FeatureName
If ($feature) {
If ($feature.Where({$_.InstallState -eq 'Available'})) {
Try {
$result = Install-WindowsFeature -Name $FeatureName -IncludeAllSubFeature:$IncludeAllSubFeature -IncludeManagementTools:$IncludeManagementTools -Restart:$Restart -WhatIf:$WhatIf
$success = $result -AND $result.Success
$status = if ($success) { [InstallStatus]::Succeeded } Else { [InstallStatus]::Failed }
}
Catch {
If ($success -AND $Restart -AND $result.restartNeeded -eq 'Yes') {
$status = [InstallStatus]::Pending
$error.clear()
} Else {
Throw
}
}
} Else {
$success = $True
$status = [InstallStatus]::AlreadyInstalled
}
} Else {
$success = $False
$status = [InstallStatus]::NoSuchFeature
}
@{ 'success' = $success ; 'status' = $status ; 'result' = $result }
}
## [END] Install-RolesAndFeatures ##
function Uninstall-RolesAndFeatures {
<#
.SYNOPSIS
UnInstalls a Feature/Role/Role Service on the target server.
.DESCRIPTION
UnInstalls a Feature/Role/Role Service on the target server, using UnInstall-WindowsFeature PowerShell cmdlet. Returns a status object
that contains the following properties:
success - true/false depending on if the overall operation Succeeded
status - status message
result - response from UnInstall-WindowsFeature call
.PARAMETER FeatureName
Is a required parameter and is the name of the Role/Feature/Role Service to un-install
.PARAMETER IncludeManagementTools
Is an optional switch parameter that is passed as a similar named parameter to Install-WindowsFeature
.PARAMETER Restart
Is an optional switch parameter that is passed as a similar named parameter to Install-WindowsFeature
.EXAMPLE
./UnInstallRolesAndFeature.ps1 -FeatureName 'ManagementOData'
Un-Installs the feature 'ManagementObject'
.EXAMPLE
./UnInstallRolesAndFeature.ps1 -FeatureName 'Web-Server' -IncludeManagementTools
Un-Installs the role 'Web-Server' and management tools
.EXAMPLE
./UnInstallRolesAndFeature.ps1 -FeatureName 'ManagementOData' -Restart
Un-Installs the feature 'ManagementObject' without management tools and reboots the server
.NOTES
The supported Operating Systems are Window Server 2012, Windows Server 2012R2, Windows Server 2016.
.ROLE
Administrators
#>
param(
[Parameter(Mandatory=$True)]
[string[]]
$FeatureName,
[Parameter(Mandatory=$False)]
[Switch]
$IncludeManagementTools,
[Parameter(Mandatory=$False)]
[Switch]
$Restart,
[Parameter(Mandatory=$False)]
[Switch]
$WhatIf
)
Import-Module ServerManager
Enum UnInstallStatus {
Failed = 0
Succeeded = 1
NoSuchFeature = 2
NotInstalled = 3
Pending = 4
}
$result = $Null
$status = $Null
$success = $False
$ErrorActionPreference = "Stop"
$feature = Get-WindowsFeature -Name $FeatureName
If ($feature) {
If ($feature.Where({$_.InstallState -eq 'Installed'})) {
Try {
$result = UnInstall-WindowsFeature -Name $FeatureName -IncludeManagementTools:$IncludeManagementTools -Restart:$Restart -WhatIf:$WhatIf
$success = $result -AND $result.Success
$status = if ($success) { [UnInstallStatus]::Succeeded } Else { [UnInstallStatus]::Failed }
}
Catch {
If ($success -AND $Restart -AND $result.restartNeeded -eq 'Yes') {
$status = [UnInstallStatus]::Pending
$error.clear()
} Else {
Throw
}
}
} Else {
$success = $True
$status = [UnInstallStatus]::NotInstalled
}
} Else {
$success = $False
$status = [UnInstallStatus]::NoSuchFeature
}
@{ 'success' = $success ; 'status' = $status ; 'result' = $result }
}
## [END] Uninstall-RolesAndFeatures ##
function Get-CimWin32ComputerSystem {
<#
.SYNOPSIS
Gets Win32_ComputerSystem object.
.DESCRIPTION
Gets Win32_ComputerSystem object.
.ROLE
Readers
#>
##SkipCheck=true##
import-module CimCmdlets
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_ComputerSystem
}
## [END] Get-CimWin32ComputerSystem ##
function Get-CimWin32LogicalDisk {
<#
.SYNOPSIS
Gets Win32_LogicalDisk object.
.DESCRIPTION
Gets Win32_LogicalDisk object.
.ROLE
Readers
#>
##SkipCheck=true##
import-module CimCmdlets
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_LogicalDisk
}
## [END] Get-CimWin32LogicalDisk ##
function Get-CimWin32NetworkAdapter {
<#
.SYNOPSIS
Gets Win32_NetworkAdapter object.
.DESCRIPTION
Gets Win32_NetworkAdapter object.
.ROLE
Readers
#>
##SkipCheck=true##
import-module CimCmdlets
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_NetworkAdapter
}
## [END] Get-CimWin32NetworkAdapter ##
function Get-CimWin32OperatingSystem {
<#
.SYNOPSIS
Gets Win32_OperatingSystem object.
.DESCRIPTION
Gets Win32_OperatingSystem object.
.ROLE
Readers
#>
##SkipCheck=true##
import-module CimCmdlets
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_OperatingSystem
}
## [END] Get-CimWin32OperatingSystem ##
function Get-CimWin32PhysicalMemory {
<#
.SYNOPSIS
Gets Win32_PhysicalMemory object.
.DESCRIPTION
Gets Win32_PhysicalMemory object.
.ROLE
Readers
#>
##SkipCheck=true##
import-module CimCmdlets
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_PhysicalMemory
}
## [END] Get-CimWin32PhysicalMemory ##
function Get-CimWin32Processor {
<#
.SYNOPSIS
Gets Win32_Processor object.
.DESCRIPTION
Gets Win32_Processor object.
.ROLE
Readers
#>
##SkipCheck=true##
import-module CimCmdlets
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_Processor
}
## [END] Get-CimWin32Processor ##
function Get-ClusterInventory {
<#
.SYNOPSIS
Retrieves the inventory data for a cluster.
.DESCRIPTION
Retrieves the inventory data for a cluster.
.ROLE
Readers
#>
import-module CimCmdlets -ErrorAction SilentlyContinue
# JEA code requires to pre-import the module (this is slow on failover cluster environment.)
import-module FailoverClusters -ErrorAction SilentlyContinue
<#
.SYNOPSIS
Get the name of this computer.
.DESCRIPTION
Get the best available name for this computer. The FQDN is preferred, but when not avaialble
the NetBIOS name will be used instead.
#>
function getComputerName() {
$computerSystem = Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue | Microsoft.PowerShell.Utility\Select-Object Name, DNSHostName
if ($computerSystem) {
$computerName = $computerSystem.DNSHostName
if ($null -eq $computerName) {
$computerName = $computerSystem.Name
}
return $computerName
}
return $null
}
<#
.SYNOPSIS
Are the cluster PowerShell cmdlets installed on this server?
.DESCRIPTION
Are the cluster PowerShell cmdlets installed on this server?
#>
function getIsClusterCmdletAvailable() {
$cmdlet = Get-Command "Get-Cluster" -ErrorAction SilentlyContinue
return !!$cmdlet
}
<#
.SYNOPSIS
Get the MSCluster Cluster CIM instance from this server.
.DESCRIPTION
Get the MSCluster Cluster CIM instance from this server.
#>
function getClusterCimInstance() {
$namespace = Get-CimInstance -Namespace root/MSCluster -ClassName __NAMESPACE -ErrorAction SilentlyContinue
if ($namespace) {
return Get-CimInstance -Namespace root/mscluster MSCluster_Cluster -ErrorAction SilentlyContinue | Microsoft.PowerShell.Utility\Select-Object fqdn, S2DEnabled
}
return $null
}
<#
.SYNOPSIS
Determines if the current cluster supports Failover Clusters Time Series Database.
.DESCRIPTION
Use the existance of the path value of cmdlet Get-StorageHealthSetting to determine if TSDB
is supported or not.
#>
function getClusterPerformanceHistoryPath() {
return $null -ne (Get-StorageSubSystem clus* | Get-StorageHealthSetting -Name "System.PerformanceHistory.Path")
}
<#
.SYNOPSIS
Get some basic information about the cluster from the cluster.
.DESCRIPTION
Get the needed cluster properties from the cluster.
#>
function getClusterInfo() {
$returnValues = @{}
$returnValues.Fqdn = $null
$returnValues.isS2DEnabled = $false
$returnValues.isTsdbEnabled = $false
$cluster = getClusterCimInstance
if ($cluster) {
$returnValues.Fqdn = $cluster.fqdn
$isS2dEnabled = !!(Get-Member -InputObject $cluster -Name "S2DEnabled") -and ($cluster.S2DEnabled -eq 1)
$returnValues.isS2DEnabled = $isS2dEnabled
if ($isS2DEnabled) {
$returnValues.isTsdbEnabled = getClusterPerformanceHistoryPath
} else {
$returnValues.isTsdbEnabled = $false
}
}
return $returnValues
}
<#
.SYNOPSIS
Are the cluster PowerShell Health cmdlets installed on this server?
.DESCRIPTION
Are the cluster PowerShell Health cmdlets installed on this server?
s#>
function getisClusterHealthCmdletAvailable() {
$cmdlet = Get-Command -Name "Get-HealthFault" -ErrorAction SilentlyContinue
return !!$cmdlet
}
<#
.SYNOPSIS
Are the Britannica (sddc management resources) available on the cluster?
.DESCRIPTION
Are the Britannica (sddc management resources) available on the cluster?
#>
function getIsBritannicaEnabled() {
return $null -ne (Get-CimInstance -Namespace root/sddc/management -ClassName SDDC_Cluster -ErrorAction SilentlyContinue)
}
<#
.SYNOPSIS
Are the Britannica (sddc management resources) virtual machine available on the cluster?
.DESCRIPTION
Are the Britannica (sddc management resources) virtual machine available on the cluster?
#>
function getIsBritannicaVirtualMachineEnabled() {
return $null -ne (Get-CimInstance -Namespace root/sddc/management -ClassName SDDC_VirtualMachine -ErrorAction SilentlyContinue)
}
<#
.SYNOPSIS
Are the Britannica (sddc management resources) virtual switch available on the cluster?
.DESCRIPTION
Are the Britannica (sddc management resources) virtual switch available on the cluster?
#>
function getIsBritannicaVirtualSwitchEnabled() {
return $null -ne (Get-CimInstance -Namespace root/sddc/management -ClassName SDDC_VirtualSwitch -ErrorAction SilentlyContinue)
}
###########################################################################
# main()
###########################################################################
$clusterInfo = getClusterInfo
$result = New-Object PSObject
$result | Add-Member -MemberType NoteProperty -Name 'Fqdn' -Value $clusterInfo.Fqdn
$result | Add-Member -MemberType NoteProperty -Name 'IsS2DEnabled' -Value $clusterInfo.isS2DEnabled
$result | Add-Member -MemberType NoteProperty -Name 'IsTsdbEnabled' -Value $clusterInfo.isTsdbEnabled
$result | Add-Member -MemberType NoteProperty -Name 'IsClusterHealthCmdletAvailable' -Value (getIsClusterHealthCmdletAvailable)
$result | Add-Member -MemberType NoteProperty -Name 'IsBritannicaEnabled' -Value (getIsBritannicaEnabled)
$result | Add-Member -MemberType NoteProperty -Name 'IsBritannicaVirtualMachineEnabled' -Value (getIsBritannicaVirtualMachineEnabled)
$result | Add-Member -MemberType NoteProperty -Name 'IsBritannicaVirtualSwitchEnabled' -Value (getIsBritannicaVirtualSwitchEnabled)
$result | Add-Member -MemberType NoteProperty -Name 'IsClusterCmdletAvailable' -Value (getIsClusterCmdletAvailable)
$result | Add-Member -MemberType NoteProperty -Name 'CurrentClusterNode' -Value (getComputerName)
$result
}
## [END] Get-ClusterInventory ##
function Get-ClusterNodes {
<#
.SYNOPSIS
Retrieves the inventory data for cluster nodes in a particular cluster.
.DESCRIPTION
Retrieves the inventory data for cluster nodes in a particular cluster.
.ROLE
Readers
#>
import-module CimCmdlets
# JEA code requires to pre-import the module (this is slow on failover cluster environment.)
import-module FailoverClusters -ErrorAction SilentlyContinue
###############################################################################
# Constants
###############################################################################
Set-Variable -Name LogName -Option Constant -Value "Microsoft-ServerManagementExperience" -ErrorAction SilentlyContinue
Set-Variable -Name LogSource -Option Constant -Value "SMEScripts" -ErrorAction SilentlyContinue
Set-Variable -Name ScriptName -Option Constant -Value $MyInvocation.ScriptName -ErrorAction SilentlyContinue
<#
.SYNOPSIS
Are the cluster PowerShell cmdlets installed?
.DESCRIPTION
Use the Get-Command cmdlet to quickly test if the cluster PowerShell cmdlets
are installed on this server.
#>
function getClusterPowerShellSupport() {
$cmdletInfo = Get-Command 'Get-ClusterNode' -ErrorAction SilentlyContinue
return $cmdletInfo -and $cmdletInfo.Name -eq "Get-ClusterNode"
}
<#
.SYNOPSIS
Get the cluster nodes using the cluster CIM provider.
.DESCRIPTION
When the cluster PowerShell cmdlets are not available fallback to using
the cluster CIM provider to get the needed information.
#>
function getClusterNodeCimInstances() {
# Change the WMI property NodeDrainStatus to DrainStatus to match the PS cmdlet output.
return Get-CimInstance -Namespace root/mscluster MSCluster_Node -ErrorAction SilentlyContinue | `
Microsoft.PowerShell.Utility\Select-Object @{Name="DrainStatus"; Expression={$_.NodeDrainStatus}}, DynamicWeight, Name, NodeWeight, FaultDomain, State
}
<#
.SYNOPSIS
Get the cluster nodes using the cluster PowerShell cmdlets.
.DESCRIPTION
When the cluster PowerShell cmdlets are available use this preferred function.
#>
function getClusterNodePsInstances() {
return Get-ClusterNode -ErrorAction SilentlyContinue | Microsoft.PowerShell.Utility\Select-Object DrainStatus, DynamicWeight, Name, NodeWeight, FaultDomain, State
}
<#
.SYNOPSIS
Use DNS services to get the FQDN of the cluster NetBIOS name.
.DESCRIPTION
Use DNS services to get the FQDN of the cluster NetBIOS name.
.Notes
It is encouraged that the caller add their approprate -ErrorAction when
calling this function.
#>
function getClusterNodeFqdn([string]$clusterNodeName) {
return ([System.Net.Dns]::GetHostEntry($clusterNodeName)).HostName
}
<#
.SYNOPSIS
Writes message to event log as warning.
.DESCRIPTION
Writes message to event log as warning.
#>
function writeToEventLog([string]$message) {
Microsoft.PowerShell.Management\New-EventLog -LogName $LogName -Source $LogSource -ErrorAction SilentlyContinue
Microsoft.PowerShell.Management\Write-EventLog -LogName $LogName -Source $LogSource -EventId 0 -Category 0 -EntryType Warning `
-Message $message -ErrorAction SilentlyContinue
}
<#
.SYNOPSIS
Get the cluster nodes.
.DESCRIPTION
When the cluster PowerShell cmdlets are available get the information about the cluster nodes
using PowerShell. When the cmdlets are not available use the Cluster CIM provider.
#>
function getClusterNodes() {
$isClusterCmdletAvailable = getClusterPowerShellSupport
if ($isClusterCmdletAvailable) {
$clusterNodes = getClusterNodePsInstances
} else {
$clusterNodes = getClusterNodeCimInstances
}
$clusterNodeMap = @{}
foreach ($clusterNode in $clusterNodes) {
$clusterNodeName = $clusterNode.Name.ToLower()
try
{
$clusterNodeFqdn = getClusterNodeFqdn $clusterNodeName -ErrorAction SilentlyContinue
}
catch
{
$clusterNodeFqdn = $clusterNodeName
writeToEventLog "[$ScriptName]: The fqdn for node '$clusterNodeName' could not be obtained. Defaulting to machine name '$clusterNodeName'"
}
$clusterNodeResult = New-Object PSObject
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'FullyQualifiedDomainName' -Value $clusterNodeFqdn
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'Name' -Value $clusterNodeName
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'DynamicWeight' -Value $clusterNode.DynamicWeight
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'NodeWeight' -Value $clusterNode.NodeWeight
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'FaultDomain' -Value $clusterNode.FaultDomain
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'State' -Value $clusterNode.State
$clusterNodeResult | Add-Member -MemberType NoteProperty -Name 'DrainStatus' -Value $clusterNode.DrainStatus
$clusterNodeMap.Add($clusterNodeName, $clusterNodeResult)
}
return $clusterNodeMap
}
###########################################################################
# main()
###########################################################################
getClusterNodes
}
## [END] Get-ClusterNodes ##
function Get-ServerInventory {
<#
.SYNOPSIS
Retrieves the inventory data for a server.
.DESCRIPTION
Retrieves the inventory data for a server.
.ROLE
Readers
#>
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) {
[Ref]$parsedVersion = $null
if (![Version]::TryParse($osVersion, $parsedVersion)) {
return $null
}
$version = [Version]$parsedVersion.Value
return New-Object Version -ArgumentList $version.Major, $version.Minor
}
<#
.SYNOPSIS
Determines if CredSSP is enabled for the current server or client.
.DESCRIPTION
Check the registry value for the CredSSP enabled state.
#>
function isCredSSPEnabled() {
Set-Variable credSSPServicePath -Option Constant -Value "WSMan:\localhost\Service\Auth\CredSSP"
Set-Variable credSSPClientPath -Option Constant -Value "WSMan:\localhost\Client\Auth\CredSSP"
$credSSPServerEnabled = $false;
$credSSPClientEnabled = $false;
$credSSPServerService = Get-Item $credSSPServicePath -ErrorAction SilentlyContinue
if ($credSSPServerService) {
$credSSPServerEnabled = [System.Convert]::ToBoolean($credSSPServerService.Value)
}
$credSSPClientService = Get-Item $credSSPClientPath -ErrorAction SilentlyContinue
if ($credSSPClientService) {
$credSSPClientEnabled = [System.Convert]::ToBoolean($credSSPClientService.Value)
}
return ($credSSPServerEnabled -or $credSSPClientEnabled)
}
<#
.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 (-not $version) {
# Since the OS version string is not properly formatted we cannot know the true installed state.
return $false
}
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
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() {
$returnValues = @{}
$returnValues.IsS2dEnabled = $false
$returnValues.IsCluster = $false
$returnValues.ClusterFqdn = $null
$namespace = Get-CimInstance -Namespace root/MSCluster -ClassName __NAMESPACE -ErrorAction SilentlyContinue
if ($namespace) {
$cluster = Get-CimInstance -Namespace root/MSCluster -ClassName MSCluster_Cluster -ErrorAction SilentlyContinue
if ($cluster) {
$returnValues.IsCluster = $true
$returnValues.ClusterFqdn = $cluster.Fqdn
$returnValues.IsS2dEnabled = !!(Get-Member -InputObject $cluster -Name "S2DEnabled") -and ($cluster.S2DEnabled -gt 0)
}
}
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 getComputerFqdnAndAddress($computerName) {
$hostEntry = [System.Net.Dns]::GetHostEntry($computerName)
$addressList = @()
foreach ($item in $hostEntry.AddressList) {
$address = New-Object PSObject
$address | Add-Member -MemberType NoteProperty -Name 'IpAddress' -Value $item.ToString()
$address | Add-Member -MemberType NoteProperty -Name 'AddressFamily' -Value $item.AddressFamily.ToString()
$addressList += $address
}
$result = New-Object PSObject
$result | Add-Member -MemberType NoteProperty -Name 'Fqdn' -Value $hostEntry.HostName
$result | Add-Member -MemberType NoteProperty -Name 'AddressList' -Value $addressList
return $result
}
<#
.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 getHostFqdnAndAddress($computerSystem) {
$computerName = $computerSystem.DNSHostName
if (!$computerName) {
$computerName = $computerSystem.Name
}
return getComputerFqdnAndAddress $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" })
$returnValues.ServerManagerAvailable = !!($namespaces | Where-Object { $_.Name -ieq "ServerManager" })
}
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:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Terminal Server\\TSAppAllowList"
$registryKeyValue = Get-ItemProperty -Path $key -Name fDisabledAllowList -ErrorAction SilentlyContinue
if (-not $registryKeyValue) {
return $false
}
return $registryKeyValue.fDisabledAllowList -eq 1
}
<#
.SYNOPSIS
Check the remote app enabled or not.
.DESCRIPTION
Check the remote app enabled or not.
#>
<#
c
.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
$fqdnAndAddress = getHostFqdnAndAddress $computerSystem
$hostname = hostname
$netbios = $env:ComputerName
$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 $fqdnAndAddress.Fqdn
$result | Add-Member -MemberType NoteProperty -Name 'AddressList' -Value $fqdnAndAddress.AddressList
$result | Add-Member -MemberType NoteProperty -Name 'Hostname' -Value $hostname
$result | Add-Member -MemberType NoteProperty -Name 'NetBios' -Value $netbios
$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 'IsWmfInstalled' -Value $isWmfInstalled
$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 'IsS2dEnabled' -Value $clusterInformation.IsS2dEnabled
$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
}

Kaynak: Dokuman Microsoft admin center üzerinden alınmıştır.