PSWinDocumentation.O365HealthService.psm1
function Convert-TimeToDays { [CmdletBinding()] param ($StartTime, $EndTime, [string] $Ignore = '*1601*') if ($null -ne $StartTime -and $null -ne $EndTime) { try { if ($StartTime -notlike $Ignore -and $EndTime -notlike $Ignore) { $Days = (New-TimeSpan -Start $StartTime -End $EndTime).Days } } catch { } } elseif ($null -ne $EndTime) { if ($StartTime -notlike $Ignore -and $EndTime -notlike $Ignore) { $Days = (New-TimeSpan -Start (Get-Date) -End ($EndTime)).Days } } elseif ($null -ne $StartTime) { if ($StartTime -notlike $Ignore -and $EndTime -notlike $Ignore) { $Days = (New-TimeSpan -Start $StartTime -End (Get-Date)).Days } } return $Days } function Find-TypesNeeded { [CmdletBinding()] param ($TypesRequired, $TypesNeeded) [bool] $Found = $False foreach ($Type in $TypesNeeded) { if ($TypesRequired -contains $Type) { $Found = $true break } } return $Found } function Get-Types { [CmdletBinding()] param ([Object] $Types) $TypesRequired = foreach ($Type in $Types) { $Type.GetEnumValues() } return $TypesRequired } function Start-TimeLog { [CmdletBinding()] param() [System.Diagnostics.Stopwatch]::StartNew() } function Stop-TimeLog { [CmdletBinding()] param ([Parameter(ValueFromPipeline = $true)][System.Diagnostics.Stopwatch] $Time, [ValidateSet('OneLiner', 'Array')][string] $Option = 'OneLiner', [switch] $Continue) Begin { } Process { if ($Option -eq 'Array') { $TimeToExecute = "$($Time.Elapsed.Days) days", "$($Time.Elapsed.Hours) hours", "$($Time.Elapsed.Minutes) minutes", "$($Time.Elapsed.Seconds) seconds", "$($Time.Elapsed.Milliseconds) milliseconds" } else { $TimeToExecute = "$($Time.Elapsed.Days) days, $($Time.Elapsed.Hours) hours, $($Time.Elapsed.Minutes) minutes, $($Time.Elapsed.Seconds) seconds, $($Time.Elapsed.Milliseconds) milliseconds" } } End { if (-not $Continue) { $Time.Stop() } return $TimeToExecute } } Add-Type -TypeDefinition @" using System; namespace PSWinDocumentation { [Flags] public enum Office365Health { All, Services, ServicesExtended, CurrentStatus, CurrentStatusExtended, HistoricalStatus, HistoricalStatusExtended, MessageCenterInformation, MessageCenterInformationExtended, Incidents, IncidentsExtended, PlannedMaintenance, PlannedMaintenanceExtended, Messages } } "@ function Connect-O365ServiceHealth { [CmdLetbinding()] param( [string][alias('ClientID')] $ApplicationID, [string][alias('ClientSecret')] $ApplicationKey, [string] $TenantDomain, [switch] $TlsDefault ) $Body = @{ grant_type = "client_credentials" resource = "https://manage.office.com" client_id = $ApplicationID client_secret = $ApplicationKey } try { if (-not $TlsDefault) { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } $Authorization = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$($TenantDomain)/oauth2/token?api-version=1.0" -Body $body -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning -Message "Connect-O365ServiceHealth - Error: $ErrorMessage" } if ($Authorization) { @{'Authorization' = "$($Authorization.token_type) $($Authorization.access_token)" } } else { $null } } function ConvertFrom-UTCTime { [CmdLetbinding()] param( [Object] $Time, [switch] $ToLocalTime ) if ($null -eq $Script:TimeZoneBias) { $TimeZoneBias = (Get-CimInstance -ClassName Win32_TimeZone).Bias } else { $TimeZoneBias = $Script:TimeZoneBias } if ($Time -is [DateTime]) { $ConvertedTime = $Time } else { if ($null -eq $Time -or $Time -eq '') { return } else { $NewTime = $Time -replace ', at', '' -replace 'UTC', '' -replace 'at' -replace '(^.+?,)' try { [DateTime] $ConvertedTime = [DateTime]::Parse($NewTime) } catch { Write-Warning "ConvertFrom-UTCTime - couldn't convert time. Please report on GitHub - $Time. Skipping conversion..." return $Time } } } if ($ToLocal) { $ConvertedTime.AddMinutes($TimeZoneBias) } else { $ConvertedTime } } function Get-Office365ServiceHealthCurrentStatus { [CmdLetbinding()] param( [System.Collections.IDictionary] $Authorization, [string] $TenantDomain, [switch] $ToLocalTime ) try { $CurrentStatus = (Invoke-RestMethod -Uri "https://manage.office.com/api/v1.0/$($TenantDomain)/ServiceComms/CurrentStatus" -Headers $Authorization -Method Get) } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning -Message "Get-Office365ServiceHealthCurrentStatus - Error: $ErrorMessage" return } $Output = @{ } $Output.Simple = foreach ($Status in $CurrentStatus.Value) { [PSCustomObject][ordered] @{ #ID = $Status.ID Service = $Status.WorkloadDisplayName #Status = $Status.Status ServiceStatus = $Status.StatusDisplayName StatusTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Status.StatusTime IncidentIds = $Status.IncidentIds -join ', ' #Workload = $Status.Workload } } $Output.Extended = foreach ($Status in $CurrentStatus.Value) { foreach ($Feature in $Status.FeatureStatus) { [PSCustomObject][ordered] @{ #ID = $Status.ID Service = $Status.WorkloadDisplayName ServiceStatus = $Status.StatusDisplayName Feature = $Feature.FeatureDisplayName FeatureStatus = $Feature.FeatureServiceStatusDisplayName IncidentIds = $Status.IncidentIds -join ', ' #Status = $Status.Status StatusTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Status.StatusTime #Workload = $Status.Workload #FeatureName = $Feature.FeatureName #FeatureServiceStatus = $Feature.FeatureServiceStatus } } } return $Output } function Get-Office365ServiceHealthHistoricalStatus { [CmdLetbinding()] param( [System.Collections.IDictionary] $Authorization, [string] $TenantDomain, [switch] $ToLocalTime ) try { $HistoricalStatus = (Invoke-RestMethod -Uri "https://manage.office.com/api/v1.0/$($TenantDomain)/ServiceComms/HistoricalStatus" -Headers $Authorization -Method Get) } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning -Message "Get-Office365ServiceHealthHistoricalStatus - Error: $ErrorMessage" return } $Output = @{ } $Output.Simple = foreach ($Status in $HistoricalStatus.Value) { $StatusTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Status.StatusTime [PSCustomObject][ordered] @{ #ID = $Status.ID Service = $Status.WorkloadDisplayName ServiceStatus = $Status.StatusDisplayName IncidentIds = $Status.IncidentIds -join ', ' #Status = $Status.Status StatusTime = $StatusTime StatusDaysAgo = Convert-TimeToDays -StartTime $StatusTime -EndTime $Script:Today #Workload = $Status.Workload } } $Output.Extended = foreach ($Status in $HistoricalStatus.Value) { foreach ($Feature in $Status.FeatureStatus) { $StatusTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Status.StatusTime [PSCustomObject][ordered] @{ #ID = $Status.ID Service = $Status.WorkloadDisplayName ServiceStatus = $Status.StatusDisplayName Feature = $Feature.FeatureDisplayName FeatureStatus = $Feature.FeatureServiceStatusDisplayName IncidentIds = $Status.IncidentIds -join ', ' #Status = $Status.Status StatusTime = $StatusTime StatusDaysAgo = Convert-TimeToDays -StartTime $StatusTime -EndTime $Script:Today #Workload = $Status.Workload #FeatureName = $Feature.FeatureName #FeatureServiceStatus = $Feature.FeatureServiceStatus } } } return $Output } function Get-Office365ServiceHealthMessages { [CmdLetbinding()] param( [System.Collections.IDictionary] $Authorization, [string] $TenantDomain, [switch] $ToLocalTime ) try { $AllMessages = (Invoke-RestMethod -Uri "https://manage.office.com/api/v1.0/$($TenantDomain)/ServiceComms/Messages" -Headers $Authorization -Method Get) } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning -Message "Get-Office365ServiceHealthMessages - Error: $ErrorMessage" return } $Output = @{ } $Simple = foreach ($Message in $AllMessages.Value) { $LastUpdatedTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Message.LastUpdatedTime [PSCustomObject][ordered] @{ Id = $Message.Id Title = $Message.Title ImpactDescription = $Message.ImpactDescription LastUpdatedTime = $LastUpdatedTime LastUpdatedDaysAgo = Convert-TimeToDays -StartTime $LastUpdatedTime -EndTime $Script:Today MessageType = $Message.MessageType Status = $Message.Status Severity = $Message.Severity StartTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Message.StartTime #Workload = $Message.Workload Workload = $Message.WorkloadDisplayName ActionType = $Message.ActionType Classification = $Message.Classification EndTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Message.EndTime #Feature = $Message.Feature Feature = $Message.FeatureDisplayName UserFunctionalImpact = $Message.UserFunctionalImpact PostIncidentDocumentUrl = $Message.PostIncidentDocumentUrl AffectedTenantCount = $Message.AffectedTenantCount AffectedUserCount = $Message.AffectedUserCount AffectedWorkload = $Message.AffectedWorkloadDisplayNames -join ',' #AffectedWorkloadNames = $Message.AffectedWorkloadNames -join ',' } } $Extended = foreach ($Message in $AllMessages.Value) { $Messages = $Message.Messages foreach ($M in $Messages) { $LastUpdatedTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Message.LastUpdatedTime $PublishedTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $M.PublishedTime [PSCustomObject][ordered] @{ Id = $Message.Id Title = $Message.Title ImpactDescription = $Message.ImpactDescription LastUpdatedTime = $LastUpdatedTime LastUpdatedDaysAgo = Convert-TimeToDays -StartTime $LastUpdatedTime -EndTime $Script:Today MessageType = $Message.MessageType Status = $Message.Status Severity = $Message.Severity StartTime = ConvertFrom-UTCTime -Time $Message.StartTime -ToLocalTime:$ToLocalTime Message = $M.MessageText PublishedTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $M.PublishedTime PublishedDaysAgo = Convert-TimeToDays -StartTime $PublishedTime -EndTime $Script:Today #Workload = $Message.Workload Workload = $Message.WorkloadDisplayName ActionType = $Message.ActionType Classification = $Message.Classification EndTime = ConvertFrom-UTCTime -ToLocalTime:$ToLocalTime -Time $Message.EndTime #Feature = $Message.Feature Feature = $Message.FeatureDisplayName UserFunctionalImpact = $Message.UserFunctionalImpact PostIncidentDocumentUrl = $Message.PostIncidentDocumentUrl AffectedTenantCount = $Message.AffectedTenantCount AffectedUserCount = $Message.AffectedUserCount AffectedWorkload = $Message.AffectedWorkloadDisplayNames -join ',' #AffectedWorkloadNames = $Message.AffectedWorkloadNames -join ',' } } } # Below this point ConvertFrom-UTCTime is not needed as rest of data is built on code above # Simplified Message Center $MessageCenterInformationSimple = foreach ($_ in $Simple) { if ($_.MessageType -eq 'MessageCenter') { $_ } } $Output.MessageCenterInformationSimple = foreach ($_ in $MessageCenterInformationSimple) { [PSCustomObject][ordered] @{ ID = $_.ID Title = $_.Title LastUpdatedTime = $_.LastUpdatedTime LastUpdatedDaysAgo = $_.LastUpdatedDaysAgo Severity = $_.Severity StartTime = $_.StartTime EndTime = $_.EndTime ActionType = $_.ActionType Classification = $_.Classification AffectedService = $_.AffectedWorkload MessageType = $_.MessageType } } # More information Message Center $MessageCenterInformation = foreach ($_ in $Extended) { if ($_.MessageType -eq 'MessageCenter') { $_ } } $Output.MessageCenterInformation = foreach ($_ in $MessageCenterInformation) { [PSCustomObject][Ordered] @{ ID = $_.ID PublishedTime = $_.PublishedTime PublishedDaysAgo = $_.PublishedDaysAgo Title = $_.Title Message = $_.Message LastUpdatedTime = $_.LastUpdatedTime LastUpdatedDaysAgo = $_.LastUpdatedDaysAgo Severity = $_.Severity StartTime = $_.StartTime EndTime = $_.EndTime ActionType = $_.ActionType Classification = $_.Classification AffectedService = $_.AffectedWorkload MessageType = $_.MessageType } } # Simplified Message Center $IncidentsSimple = foreach ($_ in $Simple) { if ($_.MessageType -eq 'Incident') { $_ } } $Output.IncidentsSimple = foreach ($_ in $IncidentsSimple) { [PSCustomObject][ordered] @{ Service = $_.Workload Feature = $_.Feature ID = $_.ID Title = $_.Title ImpactDescription = $_.ImpactDescription LastUpdatedTime = $_.LastUpdatedTime LastUpdatedDaysAgo = $_.LastUpdatedDaysAgo UserFunctionalImpact = $_.UserFunctionalImpact PostIncidentDocumentUrl = $_.PostIncidentDocumentUrl Severity = $_.Severity StartTime = $_.StartTime EndTime = $_.EndTime #ActionType = $_.ActionType Classification = $_.Classification #AffectedService = $_.AffectedWorkload AffectedTenantCount = $_.AffectedTenantCount AffectedUserCount = $_.AffectedUserCount MessageType = $_.MessageType } } # More information Message Center $Incidents = foreach ($_ in $Extended) { if ($_.MessageType -eq 'Incident') { $_ } } $Output.Incidents = foreach ($_ in $Incidents) { [PSCustomObject][Ordered] @{ Service = $_.Workload Feature = $_.Feature ID = $_.ID Title = $_.Title ImpactDescription = $_.ImpactDescription PublishedTime = $_.PublishedTime PublishedDaysAgo = $_.PublishedDaysAgo Message = $_.Message LastUpdatedTime = $_.LastUpdatedTime LastUpdatedDaysAgo = $_.LastUpdatedDaysAgo UserFunctionalImpact = $_.UserFunctionalImpact PostIncidentDocumentUrl = $_.PostIncidentDocumentUrl Severity = $_.Severity StartTime = $_.StartTime EndTime = $_.EndTime #ActionType = $_.ActionType Classification = $_.Classification #AffectedService = $_.AffectedWorkload AffectedTenantCount = $_.AffectedTenantCount AffectedUserCount = $_.AffectedUserCount MessageType = $_.MessageType } } $Output.Messages = foreach ($Entry in $Extended) { $LimitedEntry = foreach ($_ in $Entry) { if ($_.MessageType -eq 'Incident') { $_ } } # Faster Where-Object foreach ($_ in $LimitedEntry) { $Object = [PsCustomObject][Ordered] @{ Service = $_.Workload Status = $_.Status PublishedTime = $_.PublishedTime PublishedDaysAgo = $_.PublishedDaysAgo Title = '' UserImpact = '' MoreInfo = '' CurrentStatus = '' ScopeOfImpact = '' StartTime = '' PreliminaryRootCause = '' NextUpdateBy = '' FinalStatus = '' Other = '' } foreach ($SubMessage in $_.Message.Split([Environment]::NewLine)) { # | Where-Object { ($_).Trim() -ne '' }) { if ($SubMessage -like 'Title: *') { $Object.Title = $SubMessage -replace 'Title: ', '' } elseif ($SubMessage -like 'User Impact: *') { $Object.UserImpact = $SubMessage -replace 'User Impact: ', '' } elseif ($SubMessage -like 'More info: *') { $Object.MoreInfo = $SubMessage -replace 'More info: ', '' } elseif ($SubMessage -like 'Current status: *') { $Object.CurrentStatus = $SubMessage -replace 'Current status: ', '' } elseif ($SubMessage -like 'Scope of impact: *') { $Object.ScopeOfImpact = $SubMessage -replace 'Scope of impact: ', '' } elseif ($SubMessage -like 'Start time: *') { $Time = $SubMessage -replace 'Start time: ', '' $Object.StartTime = ConvertFrom-UTCTime -Time $Time -ToLocalTime:$ToLocalTime } elseif ($SubMessage -like 'Preliminary root cause: *') { $Object.PreliminaryRootCause = $SubMessage -replace 'Preliminary root cause: ', '' } elseif ($SubMessage -like 'Next update by: *') { $Time = ($SubMessage -replace 'Next update by: ', '').Trim() $Object.NextUpdateBy = ConvertFrom-UTCTime -Time $Time -ToLocalTime:$ToLocalTime } elseif ($SubMessage -like 'Final status: *') { $Object.FinalStatus = ($SubMessage -replace 'Final status: ', '').Trim() } else { $Object.Other = $SubMessage.Trim() } } $Object } } #$Output.IncidentsSimple = foreach ($_ in $Simple) { if ($_.MessageType -eq 'Incident') { $_ }} #$Output.Incidents = foreach ($_ in $Extended) { if ($_.MessageType -eq 'Incident') { $_ }} $Output.PlannedMaintenanceSimple = foreach ($_ in $Simple) { if ($_.MessageType -eq 'PlannedMaintenance') { $_ } } $Output.PlannedMaintenance = foreach ($_ in $Extended) { if ($_.MessageType -eq 'PlannedMaintenance') { $_ } } return $Output } function Get-Office365ServiceHealthServices { [CmdLetbinding()] param( [System.Collections.IDictionary] $Authorization, [string] $TenantDomain ) try { $Services = (Invoke-RestMethod -Uri "https://manage.office.com/api/v1.0/$($TenantDomain)/ServiceComms/Services" -Headers $Authorization -Method Get) } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning -Message "Get-Office365ServiceHealthServices - Error: $ErrorMessage" return } $Output = @{ } $Output.Simple = foreach ($Service in $Services.Value) { [PSCustomObject][ordered] @{ #ID = $Service.ID Service = $Service.DisplayName } } $Output.Extended = foreach ($Service in $Services.Value) { foreach ($Feature in $Service.Features) { [PSCustomObject][ordered] @{ #ID = $Service.ID Service = $Service.DisplayName Feature = $Feature.DisplayName #FeatureName = $Feature.Name } } } return $Output } function Get-Office365Health { [CmdLetbinding()] param( [string][alias('ClientID')] $ApplicationID, [string][alias('ClientSecret')] $ApplicationKey, [string] $TenantDomain, [PSWinDocumentation.Office365Health[]] $TypesRequired = [PSWinDocumentation.Office365Health]::All, [switch] $ToLocalTime, [switch] $TlsDefault ) $StartTime = Start-TimeLog $Script:TimeZoneBias = (Get-CimInstance -ClassName Win32_TimeZone).Bias $Script:Today = Get-Date if ($null -eq $TypesRequired -or $TypesRequired -contains [PSWinDocumentation.Office365Health]::All) { $TypesRequired = Get-Types -Types ([PSWinDocumentation.Office365Health]) } $Authorization = Connect-O365ServiceHealth -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain -TlsDefault:$TlsDefault if ($null -ne $Authorization) { if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.Office365Health]::Services, [PSWinDocumentation.Office365Health]::ServicesExtended)) { $Services = Get-Office365ServiceHealthServices -Authorization $Authorization -TenantDomain $TenantDomain } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.Office365Health]::CurrentStatus, [PSWinDocumentation.Office365Health]::CurrentStatusExtended )) { $CurrentStatus = Get-Office365ServiceHealthCurrentStatus -Authorization $Authorization -TenantDomain $TenantDomain -ToLocalTime:$ToLocalTime } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.Office365Health]::HistoricalStatus, [PSWinDocumentation.Office365Health]::HistoricalStatusExtended )) { $HistoricalStatus = Get-Office365ServiceHealthHistoricalStatus -Authorization $Authorization -TenantDomain $TenantDomain -ToLocalTime:$ToLocalTime } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.Office365Health]::Incidents, [PSWinDocumentation.Office365Health]::IncidentsExtended, [PSWinDocumentation.Office365Health]::MessageCenterInformation, [PSWinDocumentation.Office365Health]::MessageCenterInformationExtended, [PSWinDocumentation.Office365Health]::PlannedMaintenance, [PSWinDocumentation.Office365Health]::PlannedMaintenanceExtended, [PSWinDocumentation.Office365Health]::Messages )) { $Messages = Get-Office365ServiceHealthMessages -Authorization $Authorization -TenantDomain $TenantDomain -ToLocalTime:$ToLocalTime } $Output = [ordered] @{ } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::Services)) { $Output.Services = $Services.Simple } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::ServicesExtended)) { $Output.ServicesExtended = $Services.Extended } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::CurrentStatus)) { $Output.CurrentStatus = $CurrentStatus.Simple } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::CurrentStatusExtended)) { $Output.CurrentStatusExtended = $CurrentStatus.Extended } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::HistoricalStatus)) { $Output.HistoricalStatus = $HistoricalStatus.Simple } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::HistoricalStatusExtended)) { $Output.HistoricalStatusExtended = $HistoricalStatus.Extended } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::MessageCenterInformation)) { $Output.MessageCenterInformation = $Messages.MessageCenterInformationSimple | Sort-Object -Property LastUpdatedTime -Descending } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::MessageCenterInformationExtended)) { $Output.MessageCenterInformationExtended = $Messages.MessageCenterInformation | Sort-Object -Property LastUpdatedTime -Descending } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::Incidents)) { $Output.Incidents = $Messages.IncidentsSimple | Sort-Object -Property LastUpdatedTime -Descending } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::Messages)) { $Output.IncidentsMessages = $Messages.Messages | Sort-Object -Property PublishedTime -Descending } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::IncidentsExtended)) { $Output.IncidentsExtended = $Messages.Incidents | Sort-Object -Property LastUpdatedTime -Descending } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::PlannedMaintenance)) { $Output.PlannedMaintenance = $Messages.PlannedMaintenanceSimple | Sort-Object -Property LastUpdatedTime -Descending } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::PlannedMaintenanceExtended)) { $Output.PlannedMaintenanceExtended = $Messages.PlannedMaintenance | Sort-Object -Property LastUpdatedTime -Descending } $EndTime = Stop-TimeLog -Time $StartTime -Option OneLiner Write-Verbose "Get-Office365Health - Time to process: $EndTime" return $Output } else { return } } Export-ModuleMember -Function @('Get-Office365Health') -Alias @() |