tests/Test-HostServerFeatures.ps1
function Test-HostServerFeatures { [CmdletBinding()] param ( [parameter()][string] $TestName = "Installed Windows Features", [parameter()][string] $TestGroup = "configuration", [parameter()][string] $Description = "Validate Windows Server roles and features for CM site systems", [parameter()][hashtable] $ScriptParams ) try { $startTime = (Get-Date) [System.Collections.Generic.List[PSObject]]$tempdata = @() # for detailed test output to return if needed $stat = "PASS" $except = "FAIL" $msg = "No issues found" Import-Module ServerManager if ($ScriptParams.ComputerName -ne $env:COMPUTERNAME) { if ($ScriptParams.Credential) { $features = Get-WindowsFeature -ComputerName $ScriptParams.ComputerName -Credential $ScriptParams.Credential -ErrorAction Stop | Sort-Object Name } else { $features = Get-WindowsFeature -ComputerName $ScriptParams.ComputerName -ErrorAction Stop | Sort-Object Name } } else { $features = Get-WindowsFeature -ErrorAction Stop | Sort-Object Name } $LogFile = Join-Path $env:TEMP "serverfeatures.log" if ($ScriptParams.Remediate -eq $True -and ([string]::IsNullOrEmpty($ScriptParams.Source))) { throw "Source parameter is required for -Remediate but was not specified" } $flist = @($CmHealthConfig.windowsfeatures.Feature) if ($flist.Count -lt 1) { throw "failed to read features list from cmhealth settings file" } $exceptions = 0 [System.Collections.Generic.List[PSObject]]$missing = @() foreach ($feature in $features) { if ($feature.Name -in $flist) { if ($feature.Installed -ne $True) { Write-Verbose "feature not installed: $($feature.Name)" if ($ScriptParams.Remediate -eq $True) { try { Write-Verbose "installing: $($Feature.Name)" if ($ScriptParams.ComputerName -ne $env:COMPUTERNAME) { if ($ScriptParams.Credential) { Install-WindowsFeature -Name "$($Feature.Name)" -ComputerName $ScriptParams.ComputerName -Credential $ScriptParams.Credential -Source $ScriptParams.Source -LogPath $LogFile -WarningAction SilentlyContinue -ErrorAction Stop } else { Install-WindowsFeature -Name "$($Feature.Name)" -ComputerName $ScriptParams.ComputerName -Source $ScriptParams.Source -LogPath $LogFile -WarningAction SilentlyContinue -ErrorAction Stop } } else { Install-WindowsFeature -Name "$($Feature.Name)" -Source $ScriptParams.Source -LogPath $LogFile -WarningAction SilentlyContinue -ErrorAction Stop } $tempdata.Add( [pscustomobject]@{ Feature = $feature.Name Status = "Remediated" Message = "Success" } ) } catch { $tempdata.Add( [pscustomobject]@{ Feature = $feature.Name Status = "ERROR" Message = $_.Exception.Message -join ';' } ) } } else { $exceptions++ $tempdata.Add( [pscustomobject]@{ Feature = $feature.Name Status = $except Message = "Not installed" } ) $missing.Add($feature.Name) } } else { Write-Verbose "feature is installed: $($feature.Name)" $tempdata.Add( [pscustomobject]@{ Feature = $feature.Name Status = "PASS" Message = "Already installed" } ) } } } if ($exceptions -gt 0) { $stat = $except $msg = "$exceptions features are missing: $($missing -join ',')" } } catch { $stat = 'ERROR' $msg = $_.Exception.Message -join ';' } finally { Write-Output $([pscustomobject]@{ TestName = $TestName TestGroup = $TestGroup TestData = $tempdata Description = $Description Status = $stat Message = $msg RunTime = $(Get-RunTime -BaseTime $startTime) Credential = $(if($ScriptParams.Credential){$($ScriptParams.Credential).UserName} else { $env:USERNAME }) }) } } |