Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 5-2-24 #2085

Merged
merged 7 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@ function Invoke-AnalyzerOsInformation {
}
Add-AnalyzedResultInformation @params
}

$params = $baseParams + @{
Details = "More Information: https://aka.ms/HC-NetFrameworkSupport"
DisplayWriteType = "Yellow"
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params
}

$displayValue = [string]::Empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function Get-ExchangeAppPoolsInformation {
$FilePath
)
if (Test-Path $FilePath) {
return (Get-Content $FilePath -Raw).Trim()
return (Get-Content $FilePath -Raw -Encoding UTF8).Trim()
}
return [string]::Empty
} `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function Get-ExchangeServerIISSettings {
$content = $null
try {
if ($exist) {
$content = (Get-Content $_ -Raw).Trim()
$content = (Get-Content $_ -Raw -Encoding UTF8).Trim()
[xml]$content | Out-Null # test to make sure it is valid
$validWebConfig = $true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function Get-IISWebApplication {
$webConfigExists = Test-Path $configurationFilePath

if ($webConfigExists) {
$webConfigContent = (Get-Content $configurationFilePath -Raw).Trim()
$webConfigContent = (Get-Content $configurationFilePath -Raw -Encoding UTF8).Trim()

try {
$linkedConfigurationLine = ([xml]$webConfigContent).configuration.assemblyBinding.linkedConfiguration.href
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function Get-IISWebSite {
$customHeaderHsts = $null

if ($webConfigExists) {
$webConfigContent = (Get-Content $configurationFilePath -Raw).Trim()
$webConfigContent = (Get-Content $configurationFilePath -Raw -Encoding UTF8).Trim()

try {
$webConfigContentXml = [xml]$webConfigContent
Expand Down
104 changes: 73 additions & 31 deletions Diagnostics/HealthChecker/Features/Get-HealthCheckerData.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,58 @@ function Get-HealthCheckerData {
return $false
}

function ExportHealthCheckerXml {
[CmdletBinding()]
[OutputType([bool])]
param(
[Parameter(Mandatory = $true)]
[object]$SaveDataObject,

[Parameter(Mandatory = $true)]
[hashtable]$ProgressParams
)
Write-Verbose "Calling: $($MyInvocation.MyCommand)"
$dataExported = $false

try {
$currentErrors = $Error.Count
$ProgressParams.Status = "Exporting Data"
Write-Progress @ProgressParams
$SaveDataObject | Export-Clixml -Path $Script:OutXmlFullPath -Encoding UTF8 -Depth 2 -ErrorAction Stop -Force
Write-Verbose "Successfully export out the data"
$dataExported = $true
} catch {
try {
Write-Verbose "Failed to Export-Clixml. Inner Exception: $_"
Write-Verbose "Converting HealthCheckerExchangeServer to json."
$outputXml = [PSCustomObject]@{
HealthCheckerExchangeServer = $null
HtmlServerValues = $null
DisplayResults = $null
}

if ($null -ne $SaveDataObject.HealthCheckerExchangeServer) {
$jsonHealthChecker = $SaveDataObject.HealthCheckerExchangeServer | ConvertTo-Json -Depth 6 -ErrorAction Stop
$outputXml.HtmlServerValues = $SaveDataObject.HtmlServerValues
$outputXml.DisplayResults = $SaveDataObject.DisplayResults
} else {
$jsonHealthChecker = $SaveDataObject | ConvertTo-Json -Depth 6 -ErrorAction Stop
}

$outputXml.HealthCheckerExchangeServer = $jsonHealthChecker | ConvertFrom-Json -ErrorAction Stop
$outputXml | Export-Clixml -Path $Script:OutXmlFullPath -Encoding UTF8 -Depth 2 -ErrorAction Stop -Force
Write-Verbose "Successfully export out the data after the convert"
$dataExported = $true
} catch {
Write-Red "Failed to Export-Clixml. Unable to export the data."
}
} finally {
# This prevents the need to call Invoke-CatchActions
Invoke-ErrorCatchActionLoopFromIndex $currentErrors
}
return $dataExported
}

Write-Verbose "Calling: $($MyInvocation.MyCommand)"
$paramWriteProgress = @{
Id = 1
Expand Down Expand Up @@ -96,10 +148,20 @@ function Get-HealthCheckerData {

try {
Invoke-SetOutputInstanceLocation -Server $serverName -FileName "HealthChecker" -IncludeServerName $true
Write-HostLog "Exchange Health Checker version $BuildVersion"

if (-not $Script:VulnerabilityReport) {
# avoid having vulnerability report having a txt file with nothing in it besides the Exchange Health Checker Version
Write-HostLog "Exchange Health Checker version $BuildVersion"
}

$HealthObject = $null
$HealthObject = Get-HealthCheckerExchangeServer -ServerName $serverNameParam
$HealthObject.OrganizationInformation = $organizationInformation

# If we successfully got the data, we want to export it out right away.
# This then allows if an exception does occur in the analysis stage,
# we then have the data output that is reproducing a problem in that section of code that we can debug.
$dataExported = ExportHealthCheckerXml -SaveDataObject $HealthObject -ProgressParams $paramWriteProgress
$paramWriteProgress.Status = "Analyzing Data"
Write-Progress @paramWriteProgress
$analyzedResults = Invoke-AnalyzerEngine -HealthServerObject $HealthObject
Expand All @@ -113,41 +175,21 @@ function Get-HealthCheckerData {
} catch {
Write-Red "Failed to Health Checker against $serverName"
$failedServerList.Add($serverName)
# Try to handle the issue so we don't get a false positive report.
Invoke-CatchActions
continue
}

$currentErrors = $Error.Count
$paramWriteProgress.Status = "Exporting Data"
Write-Progress @paramWriteProgress

try {
$analyzedResults | Export-Clixml -Path $Script:OutXmlFullPath -Encoding UTF8 -Depth 2 -ErrorAction Stop
Write-Verbose "Successfully export out the data"
} catch {
try {
Write-Verbose "Failed to Export-Clixml. Inner Exception: $_"
Write-Verbose "Converting HealthCheckerExchangeServer to json."
$jsonHealthChecker = $analyzedResults.HealthCheckerExchangeServer | ConvertTo-Json -Depth 6 -ErrorAction Stop

$testOutputXml = [PSCustomObject]@{
HealthCheckerExchangeServer = $jsonHealthChecker | ConvertFrom-Json -ErrorAction Stop
HtmlServerValues = $analyzedResults.HtmlServerValues
DisplayResults = $analyzedResults.DisplayResults
}

$testOutputXml | Export-Clixml -Path $Script:OutXmlFullPath -Encoding UTF8 -Depth 2 -ErrorAction Stop
Write-Verbose "Successfully export out the data after the convert"
} catch {
Write-Red "Failed to Export-Clixml. Unable to export the data."
if ($null -eq $HealthObject) {
# Try to handle the issue so we don't get a false positive report.
Invoke-CatchActions
}
continue
} finally {
# This prevents the need to call Invoke-CatchActions
Invoke-ErrorCatchActionLoopFromIndex $currentErrors

if ($null -ne $analyzedResults) {
# Export out the analyzed data, as this is needed for Build HTML Report.
$dataExported = ExportHealthCheckerXml -SaveDataObject $analyzedResults -ProgressParams $paramWriteProgress
}

# for now don't want to display that we output the information if ReturnDataCollectionOnly is false
if (-not $ReturnDataCollectionOnly) {
if ($dataExported -and -not $ReturnDataCollectionOnly) {
Write-Grey("Output file written to {0}" -f $Script:OutputFullPath)
Write-Grey("Exported Data Object Written to {0} " -f $Script:OutXmlFullPath)
}
Expand Down
12 changes: 12 additions & 0 deletions Diagnostics/HealthChecker/Features/Invoke-VulnerabilityReport.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
function Invoke-VulnerabilityReport {

Write-Verbose "Calling: $($MyInvocation.MyCommand)"
$currentErrors = $Error.Count

if ((-not $SkipVersionCheck) -and
(Test-ScriptVersion -AutoUpdate -VersionsUrl "https://aka.ms/HC-VersionsUrl")) {
Write-Yellow "Script was updated. Please rerun the command."
return
} else {
$Script:DisplayedScriptVersionAlready = $true
Write-Green "Exchange Health Checker version $BuildVersion"
}

Invoke-ErrorCatchActionLoopFromIndex $currentErrors
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
Set-ADServerSettings -ViewEntireForest $true
$exchangeServers = @(Get-ExchangeServer)
Expand Down
3 changes: 2 additions & 1 deletion Diagnostics/HealthChecker/Helpers/Get-ErrorsThatOccurred.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ function Get-ErrorsThatOccurred {
}

if ($Error.Count -gt 0) {
Write-Grey(" "); Write-Grey(" ")
Write-Host ""
Write-Host ""
function Write-Errors {
Write-Verbose "`r`n`r`nErrors that occurred that wasn't handled"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,27 @@ function Get-ExportedHealthCheckerFiles {

$groupResults |
ForEach-Object {
if ($_.Count -gt 1) {
$groupData = $_.Group
$fileName = ($groupData | Sort-Object FileName -Descending | Select-Object -First 1).FileObject.VersionInfo.FileName
} else {
$fileName = ($_.Group).FileObject.VersionInfo.FileName
}
$sortedGroup = $_.Group | Sort-Object FileName -Descending
$index = 0
$continueLoop = $true

$data = Import-Clixml -Path $fileName
if ($null -ne $data) {
$importedItems.Add($data)
}
do {
$fileName = $sortedGroup[$index].FileObject.VersionInfo.FileName
$data = Import-Clixml -Path $fileName

if ($null -ne $data -and
$null -ne $data.HealthCheckerExchangeServer) {
Write-Verbose "For Server $($_.Group[0].ServerName) using file: $fileName"
$importedItems.Add($data)
$continueLoop = $false
} else {
$index++
if ($index -ge $_.Count) {
$continueLoop = $false
Write-Red "Failed to find proper Health Checker data to import for server $($_.Group[0].ServerName)"
}
}
} while ($continueLoop)
}
}
end {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ Describe "Testing Health Checker by Mock Data Imports" {
Mock Get-ExSetupFileVersionInfo { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\ExSetup1.xml" }
Mock Get-WebSite -ParameterFilter { $Name -eq "Default Web Site" } -MockWith { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\IIS\GetWebSite_DefaultWebSite1.xml" }
Mock Get-WebConfigFile -ParameterFilter { $PSPath -eq "IIS:\Sites\Default Web Site" } -MockWith { return [PSCustomObject]@{ FullName = "$Script:MockDataCollectionRoot\Exchange\IIS\DefaultWebSite_web2.config" } }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost2.config" -Raw }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost2.config" -Raw -Encoding UTF8 }
Mock Get-DynamicDistributionGroup { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetDynamicDistributionGroupPfMailboxes1.xml" }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Get TokenCacheModule version information" } -MockWith { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\IIS\GetVersionInformationCachToknPatched.xml" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Describe "Testing Health Checker by Mock Data Imports" {
# Needs to be like this to match the filter
Mock Get-WebConfigFile -ParameterFilter { $PSPath -eq "IIS:\Sites\Exchange Back End/ecp" } -MockWith { return [PSCustomObject]@{ FullName = "$Script:MockDataCollectionRoot\Exchange\IIS\ClientAccess\ecp\web.config" } }
Mock Get-WebConfigFile -ParameterFilter { $PSPath -eq "IIS:\Sites\Default Web Site/ecp" } -MockWith { return [PSCustomObject]@{ FullName = "$Script:MockDataCollectionRoot\Exchange\IIS\DefaultWebSite_web.config" } }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost1.config" -Raw }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost1.config" -Raw -Encoding UTF8 }
Mock Get-ExchangeDiagnosticInfo { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetExchangeDiagnosticInfo1.xml" }
Mock Get-IISModules { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetIISModulesNoTokenCacheModule.xml" }
Mock Get-Service {
Expand Down Expand Up @@ -221,9 +221,9 @@ Describe "Testing Health Checker by Mock Data Imports" {
Mock Get-AcceptedDomain { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetAcceptedDomain_Bad.xml" }
Mock Get-DnsClient { return Import-Clixml "$Script:MockDataCollectionRoot\OS\GetDnsClient1.xml" }
Mock Get-ExSetupFileVersionInfo { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\ExSetup1.xml" }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost1.config" -Raw }
Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Search\Ceres\Runtime\1.0\noderunner.exe.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\noderunner.exe1.config" -Raw }
Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\EdgeTransport.exe1.config" -Raw }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost1.config" -Raw -Encoding UTF8 }
Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Search\Ceres\Runtime\1.0\noderunner.exe.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\noderunner.exe1.config" -Raw -Encoding UTF8 }
Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\EdgeTransport.exe1.config" -Raw -Encoding UTF8 }

SetDefaultRunOfHealthChecker "Debug_Scenario2_Results.xml"
}
Expand Down Expand Up @@ -309,7 +309,7 @@ Describe "Testing Health Checker by Mock Data Imports" {
Mock Get-WmiObjectHandler -ParameterFilter { $Class -eq "Win32_Processor" } `
-MockWith { return Import-Clixml "$Script:MockDataCollectionRoot\Hardware\Physical_Win32_Processor1.xml" }
Mock Get-ExSetupFileVersionInfo { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\ExSetup1.xml" }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost2.config" -Raw }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost2.config" -Raw -Encoding UTF8 }

SetDefaultRunOfHealthChecker "Debug_Scenario3_Physical_Results.xml"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Describe "Exchange 2019 Scenarios testing 2" {
BeforeAll {
Mock Get-WmiObjectHandler -ParameterFilter { $Class -eq "Win32_PageFileSetting" } `
-MockWith { return Import-Clixml "$Script:MockDataCollectionRoot\OS\Win32_PageFileWellConfigured.xml" }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\BadApplicationHost.config" -Raw }
Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\BadApplicationHost.config" -Raw -Encoding UTF8 }
Mock Get-WebApplication -MockWith { throw "Error - Pester" }
Mock Get-WebSite -ParameterFilter { $null -eq $Name } -MockWith { throw "Error - Pester" }
Mock Get-WebSite -ParameterFilter { $Name -eq "Default Web Site" } -MockWith { throw "Error - Pester" }
Expand Down
Loading
Loading