diff --git a/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerExchangeInformation.ps1 b/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerExchangeInformation.ps1 index 066a7cb4cb..b3a6d2038f 100644 --- a/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerExchangeInformation.ps1 +++ b/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerExchangeInformation.ps1 @@ -335,7 +335,13 @@ function Invoke-AnalyzerExchangeInformation { } } } else { - $displayMissingGroups.Add("Unable to determine Local System Membership as the results were blank.") + if ($null -ne $exchangeInformation.ADComputerObject.LocalGroupMemberException -and + $exchangeInformation.ADComputerObject.LocalGroupMemberException.Exception -is [System.InvalidOperationException] -and + $HealthServerObject.OSInformation.BuildInformation.BuildVersion -lt [System.Version]"10.0.26100") { + $displayMissingGroups.Add("Unable to determine Local System Membership. This can occur when orphaned SIDs exist in the local Administrators group.") + } else { + $displayMissingGroups.Add("Unable to determine Local System Membership as the results were blank.") + } } if ($null -ne $exchangeInformation.ADComputerObject.ADGroupMembership -and diff --git a/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerOsInformation.ps1 b/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerOsInformation.ps1 index 83201b4925..677aeea0a9 100644 --- a/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerOsInformation.ps1 +++ b/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerOsInformation.ps1 @@ -400,7 +400,7 @@ function Invoke-AnalyzerOsInformation { $displayWriteType2012 = "Green" $displayValue2012 = "$($installed2012.DisplayVersion) Version is current" } elseif (Test-VisualCRedistributableInstalled -Year 2012 -Installed $osInformation.VcRedistributable) { - $displayValue2012 = "Redistributable ($($installed2012.DisplayVersion)) is outdated" + $displayValue2012 = "Redistributable is outdated ($($installed2012.DisplayVersion)). Update the Visual C++ 2012 version." $displayWriteType2012 = "Yellow" } @@ -408,7 +408,7 @@ function Invoke-AnalyzerOsInformation { $displayWriteType2013 = "Green" $displayValue2013 = "$($installed2013.DisplayVersion) Version is current" } elseif (Test-VisualCRedistributableInstalled -Year 2013 -Installed $osInformation.VcRedistributable) { - $displayValue2013 = "Redistributable ($($installed2013.DisplayVersion)) is outdated" + $displayValue2013 = "Redistributable is outdated ($($installed2013.DisplayVersion)). Update the Visual C++ 2013 version." $displayWriteType2013 = "Yellow" } } @@ -435,7 +435,7 @@ function Invoke-AnalyzerOsInformation { $displayWriteType2012 -eq "Yellow") { $params = $baseParams + @{ - Details = "Note: For more information about the latest C++ Redistributable please visit: https://aka.ms/HC-LatestVC`r`n`t`tThis is not a requirement to upgrade, only a notification to bring to your attention." + Details = "Note: Exchange requires the Visual C++ 2012 and 2013 Redistributable specifically. These are not replaced by newer versions.`r`n`t`tFor more information please visit: https://aka.ms/HC-LatestVC" DisplayWriteType = "Yellow" DisplayCustomTabNumber = 2 } diff --git a/Diagnostics/HealthChecker/Analyzer/Security/Invoke-AnalyzerSecurityMitigationService.ps1 b/Diagnostics/HealthChecker/Analyzer/Security/Invoke-AnalyzerSecurityMitigationService.ps1 index 29b323d69b..7228a475ae 100644 --- a/Diagnostics/HealthChecker/Analyzer/Security/Invoke-AnalyzerSecurityMitigationService.ps1 +++ b/Diagnostics/HealthChecker/Analyzer/Security/Invoke-AnalyzerSecurityMitigationService.ps1 @@ -129,7 +129,7 @@ function Invoke-AnalyzerSecurityMitigationService { } $params = $baseParams + @{ - Details = "Run: 'Get-Mitigations.ps1' from: '$ExScripts' to learn more." + Details = "Run: 'Get-Mitigations.ps1' from: '$([System.IO.Path]::Combine($exchangeInformation.RegistryValues.MsiInstallPath, "Scripts"))' to learn more." DisplayCustomTabNumber = 2 } Add-AnalyzedResultInformation @params diff --git a/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Invoke-JobExchangeInformationLocal.ps1 b/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Invoke-JobExchangeInformationLocal.ps1 index d491a90c4d..5b8ac4eabb 100644 --- a/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Invoke-JobExchangeInformationLocal.ps1 +++ b/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Invoke-JobExchangeInformationLocal.ps1 @@ -124,6 +124,7 @@ function Invoke-JobExchangeInformationLocal { $localGroupMember = Get-LocalGroupMember -SID "S-1-5-32-544" -ErrorAction Stop } catch { Write-Verbose "Failed to run Get-LocalGroupMember. Inner Exception: $_" + $localGroupMemberException = $_ Invoke-CatchActions } } @@ -210,6 +211,7 @@ function Invoke-JobExchangeInformationLocal { IanaTimeZoneMappingsRaw = $ianaTimeZoneMappingContent FileContentInformation = $fileContentInformation LocalGroupMember = $localGroupMember + LocalGroupMemberException = $localGroupMemberException RemoteJob = $true -eq $PSSenderInfo JobHandledErrors = $jobHandledErrors AllErrors = $Error diff --git a/Diagnostics/HealthChecker/Features/Get-HealthCheckerDataObject.ps1 b/Diagnostics/HealthChecker/Features/Get-HealthCheckerDataObject.ps1 index 3c0cee610c..2fd4eddc4b 100644 --- a/Diagnostics/HealthChecker/Features/Get-HealthCheckerDataObject.ps1 +++ b/Diagnostics/HealthChecker/Features/Get-HealthCheckerDataObject.ps1 @@ -127,9 +127,10 @@ function Get-HealthCheckerDataObject { VirtualDirectories = $ExchangeCmdletResult.VirtualDirectories ExchangeCertificateInformation = $exchangeCertificateInformation ADComputerObject = [PSCustomObject]@{ - ADObject = $ExchangeCmdletResult.ADObject.ComputerObject - ADGroupMembership = $ExchangeCmdletResult.ADObject.GroupMembership - LocalGroupMember = $ExchangeLocalResult.LocalGroupMember + ADObject = $ExchangeCmdletResult.ADObject.ComputerObject + ADGroupMembership = $ExchangeCmdletResult.ADObject.GroupMembership + LocalGroupMember = $ExchangeLocalResult.LocalGroupMember + LocalGroupMemberException = $ExchangeLocalResult.LocalGroupMemberException } AES256CBCInformation = $ExchangeLocalResult.AES256CBCInformation ApplicationConfigFileStatus = $ExchangeLocalResult.ApplicationConfigFileStatus diff --git a/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 b/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 index 5cb5b5bb18..9cd842d7fd 100644 --- a/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 @@ -58,8 +58,8 @@ Describe "Testing Health Checker by Mock Data Imports - Exchange 2016" { TestObjectMatch "Power Plan" "Balanced --- Error"-WriteType "Red" $httpProxy = GetObject "Http Proxy Setting" $httpProxy.ProxyAddress | Should -Be "None" - TestObjectMatch "Visual C++ 2012 x64" "Redistributable (11.0.50727) is outdated" -WriteType "Yellow" - TestObjectMatch "Visual C++ 2013 x64" "Redistributable (12.0.21005) is outdated" -WriteType "Yellow" + TestObjectMatch "Visual C++ 2012 x64" "Redistributable is outdated (11.0.50727). Update the Visual C++ 2012 version." -WriteType "Yellow" + TestObjectMatch "Visual C++ 2013 x64" "Redistributable is outdated (12.0.21005). Update the Visual C++ 2013 version." -WriteType "Yellow" TestObjectMatch "Server Pending Reboot" $false $pageFile = GetObject "PageFile Size 0" diff --git a/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 b/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 index 4ad67cffc8..2d13fcae33 100644 --- a/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 @@ -127,7 +127,7 @@ Describe "Testing Health Checker by Mock Data Imports" { $httpProxy = GetObject "Http Proxy Setting" $httpProxy.ProxyAddress | Should -Be "None" TestObjectMatch "Visual C++ 2012 x64" "11.0.61030 Version is current" -WriteType "Green" - TestObjectMatch "Visual C++ 2013 x64" "Redistributable (12.0.21005) is outdated" -WriteType "Yellow" + TestObjectMatch "Visual C++ 2013 x64" "Redistributable is outdated (12.0.21005). Update the Visual C++ 2013 version." -WriteType "Yellow" TestObjectMatch "Server Pending Reboot" $false $pageFile = GetObject "PageFile Size 0" diff --git a/docs/Diagnostics/HealthChecker/VisualCRedistributableVersionCheck.md b/docs/Diagnostics/HealthChecker/VisualCRedistributableVersionCheck.md index 25620d875c..a1f1ff596a 100644 --- a/docs/Diagnostics/HealthChecker/VisualCRedistributableVersionCheck.md +++ b/docs/Diagnostics/HealthChecker/VisualCRedistributableVersionCheck.md @@ -2,7 +2,9 @@ **Description:** -We check if the the latest Visual C++ Redistributable version, required for the installed Exchange server role, is installed or not. +We check if the Visual C++ Redistributable versions required for the installed Exchange server role are installed and up to date. Exchange Server specifically requires the [Visual C++ 2012 (VC++ 11.0)](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2012-vc-110-update-4-no-longer-supported) and [Visual C++ 2013 (VC++ 12.0)](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2013-vc-120-no-longer-supported) Redistributable. These older versions are **not** replaced by newer Visual C++ Redistributable versions (e.g., the latest Visual C++ 2015-2022 Redistributable) and must remain installed. + +When Health Checker reports that a version is "outdated", it means the installed version of that specific year's Redistributable (2012 or 2013) needs to be updated to the latest release within that same series. **Included in HTML Report?**