tests/Test-ServerFeatures.ps1
function Test-ServerFeatures { [CmdletBinding()] param ( [parameter()][string] $TestName = "Windows Server Features", [parameter()][string] $TestGroup = "configuration", [parameter()][string] $Description = "Validate Windows Server roles and features for CM site systems", [parameter()][hashtable] $ScriptParams, [parameter()][string] $Source = "" ) try { [System.Collections.Generic.List[PSObject]]$tempdata = @() # for detailed test output to return if needed $stat = "PASS" $msg = "No issues found" Import-Module ServerManager $features = Get-WindowsFeature $LogFile = Join-Path $env:TEMP "serverfeatures.log" if ($Remediate -eq $True -and ([string]::IsNullOrEmpty($Source))) { throw "Source parameter is required for -Remediate but was not specified" } $flist = @( 'Web-Server', # Web Server (IIS) 'Web-WebServer', # Web Server 'Web-Common-Http', # Common HTTP Features 'Web-Default-Doc', # Default Document 'Web-Dir-Browsing', # Directory Browsing 'Web-Http-Errors', # HTTP Errors 'Web-Static-Content', # Static Content 'Web-Http-Redirect', # HTTP Redirection 'Web-Health', # Health and Diagnostics 'Web-Http-Logging', # HTTP Logging 'Web-Log-Libraries', # Logging Tools 'Web-Request-Monitor', # Request Monitor 'Web-Http-Tracing', # Tracing 'Web-Performance', # Performance 'Web-Stat-Compression', # Static Content Compression 'Web-Filtering', # Request Filtering 'Web-Windows-Auth', # Windows Authentication 'Web-Net-Ext', # .NET Extensibility 3.5 'Web-Net-Ext45', # .NET Extensibility 4.6 'Web-Asp-Net45', # ASP.NET 4.6 'Web-ISAPI-Ext', # ISAPI Extensions 'Web-ISAPI-Filter', # ISAPI Filters 'Web-Mgmt-Tools', # Management Tools 'Web-Mgmt-Console', # IIS Management Console 'Web-Mgmt-Compat', # IIS 6 Management Compatibility 'Web-Metabase', # IIS 6 Metabase Compatibility 'Web-Lgcy-Mgmt-Console', # IIS 6 Management Console 'Web-Lgcy-Scripting', # IIS 6 Scripting Tools 'Web-WMI', # IIS 6 WMI Compatibility 'Web-Scripting-Tools', # IIS Management Scripts and Tools 'Web-Mgmt-Service', # Management Service 'UpdateServices-Services', # WSUS Services 'UpdateServices-DB', # SQL Server Connectivity 'NET-Framework-Features', # .NET Framework 3.5 Features 'NET-Framework-Core', # .NET Framework 3.5 (includes .NET 2.0 and 3.0) 'NET-HTTP-Activation', # HTTP Activation 'NET-Framework-45-Features', # .NET Framework 4.6 Features 'NET-Framework-45-Core', # .NET Framework 4.6 'NET-Framework-45-ASPNET', # ASP.NET 4.6 'NET-WCF-Services45', # WCF Services 'NET-WCF-HTTP-Activation45', # HTTP Activation 'NET-WCF-TCP-Activation45', # TCP Activation 'NET-WCF-TCP-PortSharing45', # TCP Port Sharing 'BITS', # Background Intelligent Transfer Service (BITS) 'BITS-IIS-Ext', # IIS Server Extension 'RDC', # Remote Differential Compression 'WAS', # Windows Process Activation Service 'WAS-Process-Model', # Process Model 'WAS-NET-Environment', # .NET Environment 3.5 'WAS-Config-APIs' # Configuration APIs ) $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.Name) is not installed!" if ($Remediate -eq $True) { try { Write-Host "installing: $($Feature.Name)" -ForegroundColor Cyan Install-WindowsFeature -Name "$($Feature.Name)" -Source $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 Statue = "FAIL" Message = "Not installed" }) $missing.Add($feature.Name) } } else { $tempdata.Add([pscustomobject]@{ Feature = $feature.Name Status = "PASS" Message = "Already installed" }) } } } if ($exceptions -gt 0) { $stat = "FAIL" $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 }) } } |