├── .github
└── FUNDING.yml
├── Build
└── Manage-Module.ps1
├── CHANGELOG.MD
├── Enums
└── Office365Health.ps1
├── Examples
├── Example-Office365Status.ps1
├── Example-Office365StatusUsingDashimo.ps1
└── Health.html
├── LICENSE
├── PSWinDocumentation.O365HealthService.psd1
├── PSWinDocumentation.O365HealthService.psm1
├── Private
├── Connect-O365ServiceHealth.ps1
├── ConvertFrom-UTCTime.ps1
├── Get-Office365ServiceHealthCurrentStatus.ps1
├── Get-Office365ServiceHealthIssues.ps1
├── Get-Office365ServiceHealthMessages.ps1
└── Get-Office365ServiceHealthServices.ps1
├── Public
└── Get-Office365Health.ps1
└── README.MD
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: PrzemyslawKlys
4 | custom: https://paypal.me/PrzemyslawKlys
--------------------------------------------------------------------------------
/Build/Manage-Module.ps1:
--------------------------------------------------------------------------------
1 | Import-Module "C:\Support\GitHub\PSPublishModule\PSPublishModule.psd1"
2 |
3 | Build-Module -ModuleName 'PSWinDocumentation.O365HealthService' {
4 | # Usual defaults as per standard module
5 | $Manifest = [ordered] @{
6 | # Version number of this module.
7 | ModuleVersion = '1.0.X'
8 | # Supported PSEditions
9 | CompatiblePSEditions = @('Desktop', 'Core')
10 | # ID used to uniquely identify this module
11 | GUID = '5879b6ed-e0da-4815-ad68-d345253bfe54'
12 | # Author of this module
13 | Author = 'Przemyslaw Klys'
14 | # Company or vendor of this module
15 | CompanyName = 'Evotec'
16 | # Copyright statement for this module
17 | Copyright = "(c) 2011 - $((Get-Date).Year) Przemyslaw Klys @ Evotec. All rights reserved."
18 | # Description of the functionality provided by this module
19 | Description = 'Office 365 Health Service'
20 | # Minimum version of the Windows PowerShell engine required by this module
21 | PowerShellVersion = '5.1'
22 | # Tags applied to this module. These help with module discovery in online galleries.
23 | Tags = @('Windows', 'Office365', 'O365', 'PSWinDocumentation', 'HealthService', 'Linux', 'Osx')
24 | # A URL to the main website for this project.
25 | ProjectUri = 'https://github.com/EvotecIT/PSWinDocumentation.O365HealthService'
26 | # A URL to an icon representing this module.
27 | IconUri = 'https://evotec.xyz/wp-content/uploads/2018/10/PSWinDocumentation.png'
28 | }
29 | New-ConfigurationManifest @Manifest
30 |
31 | # Add standard module dependencies (directly, but can be used with loop as well)
32 | New-ConfigurationModule -Type RequiredModule -Name 'PSSharedGoods' -Guid 'Auto' -Version 'Latest'
33 | New-ConfigurationModule -Type RequiredModule -Name 'Graphimo' -Guid 'Auto' -Version 'Latest'
34 |
35 | # Add approved modules, that can be used as a dependency, but only when specific function from those modules is used
36 | # And on that time only that function and dependant functions will be copied over
37 | # Keep in mind it has it's limits when "copying" functions such as it should not depend on DLLs or other external files
38 | New-ConfigurationModule -Type ApprovedModule -Name 'PSSharedGoods', 'PSWriteColor', 'Connectimo', 'PSUnifi', 'PSWebToolbox', 'PSMyPassword', 'PSPublishModule', 'Graphimo'
39 |
40 | New-ConfigurationModuleSkip -IgnoreModuleName @(
41 | # built-in modules in PowerShell
42 | 'Microsoft.PowerShell.Management'
43 | 'Microsoft.PowerShell.Utility'
44 | 'Microsoft.PowerShell.LocalAccounts'
45 | 'Microsoft.WSMan.Management'
46 | 'Microsoft.PowerShell.Security'
47 | 'NetTCPIP'
48 | # Graphimo uses it, but only in specific circumstances. This module doesn't
49 | 'MSAL.PS'
50 | )
51 |
52 | $ConfigurationFormat = [ordered] @{
53 | RemoveComments = $false
54 |
55 | PlaceOpenBraceEnable = $true
56 | PlaceOpenBraceOnSameLine = $true
57 | PlaceOpenBraceNewLineAfter = $true
58 | PlaceOpenBraceIgnoreOneLineBlock = $false
59 |
60 | PlaceCloseBraceEnable = $true
61 | PlaceCloseBraceNewLineAfter = $true
62 | PlaceCloseBraceIgnoreOneLineBlock = $false
63 | PlaceCloseBraceNoEmptyLineBefore = $true
64 |
65 | UseConsistentIndentationEnable = $true
66 | UseConsistentIndentationKind = 'space'
67 | UseConsistentIndentationPipelineIndentation = 'IncreaseIndentationAfterEveryPipeline'
68 | UseConsistentIndentationIndentationSize = 4
69 |
70 | UseConsistentWhitespaceEnable = $true
71 | UseConsistentWhitespaceCheckInnerBrace = $true
72 | UseConsistentWhitespaceCheckOpenBrace = $true
73 | UseConsistentWhitespaceCheckOpenParen = $true
74 | UseConsistentWhitespaceCheckOperator = $true
75 | UseConsistentWhitespaceCheckPipe = $true
76 | UseConsistentWhitespaceCheckSeparator = $true
77 |
78 | AlignAssignmentStatementEnable = $true
79 | AlignAssignmentStatementCheckHashtable = $true
80 |
81 | UseCorrectCasingEnable = $true
82 | }
83 | # format PSD1 and PSM1 files when merging into a single file
84 | # enable formatting is not required as Configuration is provided
85 | New-ConfigurationFormat -ApplyTo 'OnMergePSM1', 'OnMergePSD1' -Sort None @ConfigurationFormat
86 | # format PSD1 and PSM1 files within the module
87 | # enable formatting is required to make sure that formatting is applied (with default settings)
88 | New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'DefaultPSM1' -EnableFormatting -Sort None
89 | # when creating PSD1 use special style without comments and with only required parameters
90 | New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'OnMergePSD1' -PSD1Style 'Minimal'
91 |
92 | # configuration for documentation, at the same time it enables documentation processing
93 | New-ConfigurationDocumentation -Enable:$false -StartClean -UpdateWhenNew -PathReadme 'Docs\Readme.md' -Path 'Docs'
94 |
95 | New-ConfigurationImportModule -ImportSelf -ImportRequiredModules
96 |
97 | New-ConfigurationBuild -Enable:$true -SignModule:$true -DeleteTargetModuleBeforeBuild -MergeFunctionsFromApprovedModules -MergeModuleOnBuild -CertificateThumbprint '483292C9E317AA13B07BB7A96AE9D1A5ED9E7703'
98 |
99 | New-ConfigurationArtefact -Type Unpacked -Enable -Path "$PSScriptRoot\..\Artefacts\Unpacked" #-RequiredModulesPath "$PSScriptRoot\..\Artefacts\Modules"
100 | New-ConfigurationArtefact -Type Packed -Enable -Path "$PSScriptRoot\..\Artefacts\Packed" -IncludeTagName
101 |
102 | # global options for publishing to github/psgallery
103 | #New-ConfigurationPublish -Type PowerShellGallery -FilePath 'C:\Support\Important\PowerShellGalleryAPI.txt' -Enabled:$true
104 | #New-ConfigurationPublish -Type GitHub -FilePath 'C:\Support\Important\GitHubAPI.txt' -UserName 'EvotecIT' -Enabled:$true
105 | }
106 |
--------------------------------------------------------------------------------
/CHANGELOG.MD:
--------------------------------------------------------------------------------
1 | ### PSWinDocumentation.O365HealthService Release History
2 |
3 | #### 1.0.4 - 2023.07.06
4 | - Fixes DateTime related issues
5 | - Improves DateTime conversion
6 | - Updates overall
7 | - Change of certificate which may require `Install-Module PSWinDocumentation.O365HealthService -Force -Vebose -SkipPublisherCheck`
8 |
9 | #### 1.0.3 - 31.01.2021
10 | - Brings back StartDate and EndDate for issues
11 |
12 | #### 1.0.2 - 31.01.2022
13 | - Fixes cross-platform timezone issue [#10](https://github.com/EvotecIT/PSWinDocumentation.O365HealthService/issues/10) - this time for real
14 |
15 | #### 1.0.1 - 31.01.2022
16 | - Fixes cross-platform timezone issue [#10](https://github.com/EvotecIT/PSWinDocumentation.O365HealthService/issues/10)
17 |
18 | #### 1.0.0 - 29.01.2022
19 | - Microsoft disabled the Health Service API. Migrated code to Graph API.
20 | - There are **breaking changes** on the output (aka a bit differently formatted information), less types, different columns, etc.
21 | - Check examples for more information.
22 | - Permission requirements changed
23 |
24 | 
25 |
26 | #### 0.2.4. -13.12.2019
27 | - Enforces TLS 1.2 as it may be problematic otherwise. Hopefully doesn't break anything
28 | - Added parameter `TlsDefault` to `Get-Office365Health -TlsDefault` as a way to circumvent that new feature, just in case. Subject to removal later on
29 | #### 0.2.3 - 7.11.2019
30 | - Optimized module removing depedencies (PSSharedGoods) on release
31 | - It's still used during development
32 | #### 0.2.2 - 13.05.2019
33 | - Fix for mispelled extended word (sorry again..)
34 | #### 0.2.1 - 08.05.2019
35 | - Fix for mispelled extended word (sorry)
36 | #### 0.2.0 - 03.05.2019
37 | - Fix for date changes that Microsoft introduced
38 | #### 0.1.0 - 22.04.2019
39 | - First public release
40 |
41 | 
--------------------------------------------------------------------------------
/Enums/Office365Health.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSWinDocumentation
5 | {
6 | [Flags]
7 | public enum Office365Health {
8 | All,
9 | Services,
10 | CurrentStatus,
11 | CurrentStatusExtended,
12 | MessageCenterInformation,
13 | MessageCenterInformationExtended,
14 | Incidents,
15 | IncidentsExtended,
16 | IncidentsUpdates
17 | }
18 | }
19 | "@
--------------------------------------------------------------------------------
/Examples/Example-Office365Status.ps1:
--------------------------------------------------------------------------------
1 | Import-Module PSWinDocumentation.O365HealthService -Force
2 |
3 | $ApplicationID = ''
4 | $ApplicationKey = ''
5 | $TenantDomain = 'evotec.pl' # CustomDomain (onmicrosoft.com won't work), alternatively you can use DirectoryID
6 |
7 | $O365 = Get-Office365Health -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain
8 | $O365
--------------------------------------------------------------------------------
/Examples/Example-Office365StatusUsingDashimo.ps1:
--------------------------------------------------------------------------------
1 | Import-Module PSWinDocumentation.O365HealthService -Force
2 | Import-Module PSWriteHTML -Force
3 |
4 | $ApplicationID = ''
5 | $ApplicationKey = ''
6 | $TenantDomain = 'evotec.pl' # CustomDomain (onmicrosoft.com won't work), alternatively you can use DirectoryID
7 |
8 | $O365 = Get-Office365Health -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain -Verbose
9 |
10 | Dashboard -FilePath $PSScriptRoot\Health.html {
11 | TabOption -BorderRadius 0px -BackgroundColorActive DimGrey
12 | SectionOption -BorderRadius 0px -HeaderBackGroundColor DimGrey
13 | TableOption -DataStore JavaScript -ArrayJoinString "; " -ArrayJoin -BoolAsString
14 | Tab -Name 'Services' {
15 | Section -Name 'Service List' {
16 | Table -DataTable $O365.Services -Filtering
17 | }
18 | }
19 | Tab -Name 'Current Status' {
20 | Section -Invisible {
21 | Section -Name 'Current Status' {
22 | Table -DataTable $O365.CurrentStatus {
23 | TableCondition -Name 'ServiceStatus' -Value 'serviceOperational' -BackgroundColor MintGreen -FailBackgroundColor Salmon
24 | } -Filtering
25 | }
26 | Section -Name 'Current Status Extended' {
27 | Table -DataTable $O365.CurrentStatusExtended {
28 | TableCondition -Name 'ServiceStatus' -Value 'serviceOperational' -BackgroundColor MintGreen -FailBackgroundColor Salmon
29 | } -Filtering
30 | }
31 | }
32 | }
33 | Tab -Name 'Message Center Information' {
34 | #Section -Invisible {
35 | Section -Name 'Message Center' {
36 | Table -DataTable $O365.MessageCenterInformation -Filtering
37 | }
38 | Section -Name 'Message Center Extended' {
39 | Table -DataTable $O365.MessageCenterInformationExtended -InvokeHTMLTags -Filtering
40 | }
41 | #}
42 | }
43 | Tab -Name 'Incidents' {
44 | Section -Invisible {
45 | Section -Name 'Incidents' {
46 | Table -DataTable $O365.Incidents -Filtering {
47 | TableCondition -Name 'IsResolved' -Value $true -BackgroundColor MintGreen -FailBackgroundColor Salmon -ComparisonType bool
48 | }
49 | }
50 | Section -Name 'Incidents Extended' {
51 | Table -DataTable $O365.IncidentsExtended -Filtering {
52 | TableCondition -Name 'IsResolved' -Value $true -BackgroundColor MintGreen -FailBackgroundColor Salmon -ComparisonType bool
53 | }
54 | }
55 | }
56 | Section -Name 'Incidents Messages' {
57 | Table -DataTable $O365.IncidentsUpdates -InvokeHTMLTags -Filtering
58 | }
59 | }
60 | } -Online -ShowHTML
--------------------------------------------------------------------------------
/Examples/Health.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Services
Current Status
Message Center Information
Incidents
876 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Evotec
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PSWinDocumentation.O365HealthService.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | AliasesToExport = @()
3 | Author = 'Przemyslaw Klys'
4 | CmdletsToExport = @()
5 | CompanyName = 'Evotec'
6 | CompatiblePSEditions = @('Desktop', 'Core')
7 | Copyright = '(c) 2011 - 2023 Przemyslaw Klys @ Evotec. All rights reserved.'
8 | Description = 'Office 365 Health Service'
9 | FunctionsToExport = 'Get-Office365Health'
10 | GUID = '5879b6ed-e0da-4815-ad68-d345253bfe54'
11 | ModuleVersion = '1.0.4'
12 | PowerShellVersion = '5.1'
13 | PrivateData = @{
14 | PSData = @{
15 | Tags = @('Windows', 'Office365', 'O365', 'PSWinDocumentation', 'HealthService', 'Linux', 'Osx')
16 | IconUri = 'https://evotec.xyz/wp-content/uploads/2018/10/PSWinDocumentation.png'
17 | ProjectUri = 'https://github.com/EvotecIT/PSWinDocumentation.O365HealthService'
18 | }
19 | }
20 | RequiredModules = @(@{
21 | ModuleName = 'PSSharedGoods'
22 | ModuleVersion = '0.0.264'
23 | Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
24 | }, @{
25 | ModuleName = 'Graphimo'
26 | ModuleVersion = '0.0.18'
27 | Guid = '48605140-a2a9-44f3-b682-3efc5cc9f2c1'
28 | })
29 | RootModule = 'PSWinDocumentation.O365HealthService.psm1'
30 | }
--------------------------------------------------------------------------------
/PSWinDocumentation.O365HealthService.psm1:
--------------------------------------------------------------------------------
1 | #Get public and private function definition files.
2 | $Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue -Recurse )
3 | $Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue -Recurse )
4 | $Classes = @( Get-ChildItem -Path $PSScriptRoot\Classes\*.ps1 -ErrorAction SilentlyContinue -Recurse )
5 | $Enums = @( Get-ChildItem -Path $PSScriptRoot\Enums\*.ps1 -ErrorAction SilentlyContinue -Recurse )
6 |
7 | $AssemblyFolders = Get-ChildItem -Path $PSScriptRoot\Lib -Directory -ErrorAction SilentlyContinue
8 | if ($AssemblyFolders.BaseName -contains 'Standard') {
9 | $Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Standard\*.dll -ErrorAction SilentlyContinue )
10 | } else {
11 | if ($PSEdition -eq 'Core') {
12 | $Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Core\*.dll -ErrorAction SilentlyContinue )
13 | } else {
14 | $Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Default\*.dll -ErrorAction SilentlyContinue )
15 | }
16 | }
17 | $FoundErrors = @(
18 | Foreach ($Import in @($Assembly)) {
19 | try {
20 | Add-Type -Path $Import.Fullname -ErrorAction Stop
21 | } catch [System.Reflection.ReflectionTypeLoadException] {
22 | Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
23 | $LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
24 | foreach ($E in $LoaderExceptions) {
25 | Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
26 | }
27 | $true
28 | #Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
29 | } catch {
30 | Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
31 | $LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
32 | foreach ($E in $LoaderExceptions) {
33 | Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
34 | }
35 | $true
36 | #Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
37 | }
38 | }
39 | #Dot source the files
40 | Foreach ($Import in @($Private + $Public + $Classes + $Enums)) {
41 | Try {
42 | . $Import.Fullname
43 | } Catch {
44 | Write-Error -Message "Failed to import functions from $($import.Fullname): $_"
45 | $true
46 | }
47 | }
48 | )
49 |
50 | if ($FoundErrors.Count -gt 0) {
51 | $ModuleName = (Get-ChildItem $PSScriptRoot\*.psd1).BaseName
52 | Write-Warning "Importing module $ModuleName failed. Fix errors before continuing."
53 | break
54 | }
55 |
56 | Export-ModuleMember -Function '*' -Alias '*'
--------------------------------------------------------------------------------
/Private/Connect-O365ServiceHealth.ps1:
--------------------------------------------------------------------------------
1 | function Connect-O365ServiceHealth {
2 | [cmdletBinding(DefaultParameterSetName = 'ClearText')]
3 | param(
4 | [parameter(Mandatory, ParameterSetName = 'Encrypted')]
5 | [parameter(Mandatory, ParameterSetName = 'ClearText')][string][alias('ClientID')] $ApplicationID,
6 | [parameter(Mandatory, ParameterSetName = 'ClearText')][string][alias('ClientSecret')] $ApplicationKey,
7 | [parameter(Mandatory, ParameterSetName = 'Encrypted')][string][alias('ClientSecretEncrypted')] $ApplicationKeyEncrypted,
8 | [parameter(Mandatory, ParameterSetName = 'Credential')][PSCredential] $Credential,
9 |
10 | [parameter(Mandatory, ParameterSetName = 'Encrypted')]
11 | [parameter(Mandatory, ParameterSetName = 'ClearText')]
12 | [parameter(Mandatory, ParameterSetName = 'Credential')]
13 | [string] $TenantDomain
14 | )
15 |
16 | $connectGraphSplat = @{
17 | ApplicationID = $ApplicationID
18 | ApplicationKey = $ApplicationKey
19 | ApplicationKeyEncrypted = $ApplicationKeyEncrypted
20 | Credential = $Credential
21 | TenantDomain = $TenantDomain
22 | Resource = 'https://graph.microsoft.com/.default'
23 | }
24 | Remove-EmptyValue -Hashtable $connectGraphSplat
25 | Connect-Graphimo @connectGraphSplat
26 | }
--------------------------------------------------------------------------------
/Private/ConvertFrom-UTCTime.ps1:
--------------------------------------------------------------------------------
1 | function ConvertFrom-UTCTime {
2 | [CmdLetbinding()]
3 | param(
4 | [Object] $Time,
5 | [switch] $ToLocalTime
6 | )
7 | if ($null -eq $Script:TimeZoneBias) {
8 | try {
9 | $TimeZoneBias = (Get-TimeZone -ErrorAction Stop).BaseUtcOffset.TotalMinutes
10 | } catch {
11 | Write-Warning "ConvertFrom-UTCTime - couldn't get timezone. Please report on GitHub."
12 | $TimeZoneBias = 0
13 | }
14 | } else {
15 | $TimeZoneBias = $Script:TimeZoneBias
16 | }
17 | if ($Time -is [DateTime]) {
18 | $ConvertedTime = $Time
19 | } else {
20 | if ($null -eq $Time -or $Time -eq '') {
21 | return
22 | } else {
23 | #Write-Verbose -Message "ConvertFrom-UTCTime - Converting time: $Time"
24 | $NewTime = $Time -replace ', at', '' -replace ' by', '' -replace 'UTC', '' -replace ' at', ''
25 | $NewTIme = $NewTime -replace 'Monday,', '' -replace 'Tuesday,', '' -replace 'Wednesday,', '' -replace 'Thursday,', '' -replace 'Friday,', '' -replace 'Saturday,', '' -replace 'Sunday,', ''
26 | try {
27 | [DateTime] $ConvertedTime = [DateTime]::Parse($NewTime)
28 | } catch {
29 | Write-Warning "ConvertFrom-UTCTime - couldn't convert time $Time (after conversion $NewTime). Exception: $($_.Exception.Message). Skipping conversion..."
30 | return $Time
31 | }
32 | }
33 | }
34 | if ($ToLocal) {
35 | $ConvertedTime.AddMinutes($TimeZoneBias)
36 | } else {
37 | $ConvertedTime
38 | }
39 | }
--------------------------------------------------------------------------------
/Private/Get-Office365ServiceHealthCurrentStatus.ps1:
--------------------------------------------------------------------------------
1 | function Get-Office365ServiceHealthCurrentStatus {
2 | [CmdLetbinding()]
3 | param(
4 | [System.Collections.IDictionary] $Authorization,
5 | [string] $TenantDomain,
6 | [switch] $ToLocalTime
7 | )
8 | try {
9 | $CurrentStatus = Invoke-Graphimo -Uri "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews?`$expand=issues" -Method GET -Headers $Authorization -FullUri
10 | } catch {
11 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
12 | Write-Warning -Message "Get-Office365ServiceHealthCurrentStatus - Error: $ErrorMessage"
13 | return
14 | }
15 | $Output = @{ }
16 | $Output.Simple = foreach ($Status in $CurrentStatus) {
17 | [PSCustomObject][ordered] @{
18 | ID = $Status.ID
19 | Service = $Status.Service
20 | ServiceStatus = $Status.Status
21 | StatusTime = $Script:Today
22 | Incidents = ($Status.issues | Where-Object { $_.IsResolved -eq $false }).id
23 | }
24 | }
25 |
26 | $Output.Extended = foreach ($Status in $CurrentStatus) {
27 | [PSCustomObject][ordered] @{
28 | ID = $Status.ID
29 | Service = $Status.Service
30 | ServiceStatus = $Status.Status
31 | StatusTime = $Script:Today
32 | Incidents = ($Status.issues | Where-Object { $_.IsResolved -eq $false }).id
33 | FeaturesAffected = ($Status.issues | Where-Object { $_.IsResolved -eq $false }).feature
34 | FeaturesAffectedGroup = ($Status.issues | Where-Object { $_.IsResolved -eq $false }).featureGroup
35 | }
36 | }
37 | return $Output
38 | }
--------------------------------------------------------------------------------
/Private/Get-Office365ServiceHealthIssues.ps1:
--------------------------------------------------------------------------------
1 | function Get-Office365ServiceHealthIssues {
2 | [CmdLetbinding()]
3 | param(
4 | [System.Collections.IDictionary] $Authorization,
5 | [switch] $ToLocalTime
6 | )
7 | try {
8 | $AllMessages = Invoke-Graphimo -Uri "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues" -Method GET -Headers $Authorization -FullUri
9 | } catch {
10 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
11 | Write-Warning -Message "Get-Office365ServiceHealthIssues - Error: $ErrorMessage"
12 | return
13 | }
14 | $Output = @{ }
15 | $Output.Incidents = foreach ($Message in $AllMessages) {
16 | [PSCustomObject] @{
17 | Id = $Message.Id
18 | Title = $Message.Title
19 | Impact = $Message.impactDescription
20 | IsResolved = $Message.IsResolved
21 | StartTime = ConvertFrom-UTCTime -Time $Message.startDateTime -ToLocalTime:$ToLocalTime.IsPresent
22 | EndTime = ConvertFrom-UTCTime -Time $Message.endDateTime -ToLocalTime:$ToLocalTime.IsPresent
23 | # HighImpact = $Message.highImpact
24 | Classification = $Message.classification
25 | Origin = $Message.origin
26 | Service = $Message.service
27 | LastUpdatedTime = ConvertFrom-UTCTime -Time $Message.lastModifiedDateTime -ToLocalTime:$ToLocalTime.IsPresent
28 | LastUpdatedDays = Convert-TimeToDays -StartTime $Message.lastModifiedDateTime -EndTime $Script:Today
29 | Status = $Message.status
30 | Feature = $Message.feature
31 | FeatureGroup = $Message.featureGroup
32 | NotifyInApp = ($Message.details | Where-Object { $_.Name -eq 'NotifyInApp' }).Value -eq $true
33 | UpdatesCount = $Message.posts.count
34 | }
35 | }
36 | $Output.IncidentsExtended = foreach ($Message in $AllMessages) {
37 | [PSCustomObject] @{
38 | Id = $Message.Id
39 | Title = $Message.Title
40 | Impact = $Message.impactDescription
41 | IsResolved = $Message.IsResolved
42 | StartTime = ConvertFrom-UTCTime -Time $Message.startDateTime -ToLocalTime
43 | EndTime = ConvertFrom-UTCTime -Time $Message.endDateTime -ToLocalTime
44 | # HighImpact = $Message.highImpact
45 | Classification = $Message.classification
46 | Origin = $Message.origin
47 | Service = $Message.service
48 | LastUpdatedTime = ConvertFrom-UTCTime -Time $Message.lastModifiedDateTime -ToLocalTime:$ToLocalTime.IsPresent
49 | LastUpdatedDays = Convert-TimeToDays -StartTime $Message.lastModifiedDateTime -EndTime $Script:Today
50 | Status = $Message.status
51 | Feature = $Message.feature
52 | FeatureGroup = $Message.featureGroup
53 | NotifyInApp = ($Message.details | Where-Object { $_.Name -eq 'NotifyInApp' }).Value -eq $true
54 | UpdatesCount = $Message.posts.count
55 | Updates = $Message.Posts | ForEach-Object {
56 | $Object = [ordered] @{}
57 | foreach ($SubMessage in $_.description.content.Split("`n")) {
58 | if ($SubMessage -like 'Title: *') {
59 | $Object.Title = $SubMessage -replace 'Title: ', ''
60 | } elseif ($SubMessage -like 'User Impact: *') {
61 | $Object.UserImpact = $SubMessage -replace 'User Impact: ', ''
62 | } elseif ($SubMessage -like 'More info: *') {
63 | $Object.MoreInfo = $SubMessage -replace 'More info: ', ''
64 | } elseif ($SubMessage -like 'Current status: *') {
65 | $Object.CurrentStatus = $SubMessage -replace 'Current status: ', ''
66 | } elseif ($SubMessage -like 'Scope of impact: *') {
67 | $Object.ScopeOfImpact = $SubMessage -replace 'Scope of impact: ', ''
68 | } elseif ($SubMessage -like 'Start time: *') {
69 | $Time = $SubMessage -replace 'Start time: ', ''
70 | $Object.StartTime = ConvertFrom-UTCTime -Time $Time -ToLocalTime:$ToLocalTime
71 | } elseif ($SubMessage -like 'Preliminary root cause: *') {
72 | $Object.PreliminaryRootCause = $SubMessage -replace 'Preliminary root cause: ', ''
73 | } elseif ($SubMessage -like 'Root cause: *') {
74 | $Object.RootCause = $SubMessage -replace 'Root cause: ', ''
75 | } elseif ($SubMessage -like 'Next update by: *') {
76 | $Time = ($SubMessage -replace 'Next update by: ', '').Trim()
77 | $Object.NextUpdateBy = ConvertFrom-UTCTime -Time $Time -ToLocalTime:$ToLocalTime
78 | } elseif ($SubMessage -like 'Final status: *') {
79 | $Object.FinalStatus = ($SubMessage -replace 'Final status: ', '').Trim()
80 | } else {
81 | $Object.Other = $SubMessage.Trim()
82 | }
83 | }
84 | [PSCustomObject] @{
85 | Id = $Message.Id
86 | Service = $Message.service
87 | Created = if ($_.createdDateTime) { [datetime]::Parse($_.createdDateTime) } else { $null }
88 | Type = $_.postType
89 | Title = $Object.Title
90 | UserImpact = $Object.UserImpact
91 | MoreInfo = $Object.MoreInfo
92 | CurrentStatus = $Object.CurrentStatus
93 | ScopeOfImpact = $Object.ScopeOfImpact
94 | StartTime = $Object.StartTime
95 | PreliminaryRootCause = $Object.PreliminaryRootCause
96 | RootCause = $Object.RootCause
97 | FinalStatus = $Object.FinalStatus
98 | NextUpdateBy = $Object.NextUpdateBy
99 | Other = $Object.Other
100 | }
101 | }
102 | }
103 | }
104 | $Output.IncidentsUpdates = foreach ($Message in $Output.IncidentsExtended) {
105 | foreach ($Post in $Message.Updates) {
106 | $Post
107 | }
108 | }
109 | $Output
110 | }
--------------------------------------------------------------------------------
/Private/Get-Office365ServiceHealthMessages.ps1:
--------------------------------------------------------------------------------
1 | function Get-Office365ServiceHealthMessages {
2 | [CmdLetbinding()]
3 | param(
4 | [System.Collections.IDictionary] $Authorization
5 | )
6 | try {
7 | $AllMessages = Invoke-Graphimo -Uri "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/messages" -Method GET -Headers $Authorization -FullUri
8 | } catch {
9 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
10 | Write-Warning -Message "Get-Office365ServiceHealthMessages - Error: $ErrorMessage"
11 | return
12 | }
13 | $Output = @{ }
14 | $Output.MessageCenterInformation = foreach ($Message in $AllMessages) {
15 | $ActionRequiredDays = Convert-TimeToDays -StartTime $Message.actionRequiredByDateTime -EndTime $Script:Today
16 | [PSCustomObject] @{
17 | Id = $Message.Id
18 | Title = $Message.Title
19 | Service = $Message.services
20 | LastUpdatedTime = if ($Message.lastModifiedDateTime) { [DateTime]::Parse($Message.lastModifiedDateTime) } else { $null }
21 | LastUpdatedDays = Convert-TimeToDays -StartTime $Message.lastModifiedDateTime -EndTime $Script:Today
22 | ActionRequiredByDateTime = if ( $Message.actionRequiredByDateTime) { [DateTime]::Parse($Message.actionRequiredByDateTime) } else { $null }
23 | ActionRequiredDays = if ($ActionRequiredDays -eq 0) { $null } else { - $ActionRequiredDays }
24 | Tags = $Message.Tags
25 | RoadmapId = ($Message.details | Where-Object { $_.name -eq 'roadmapids' }).Value
26 | Category = $Message.category
27 | }
28 | }
29 | $Output.MessageCenterInformationExtended = foreach ($Message in $AllMessages) {
30 | $ActionRequiredDays = Convert-TimeToDays -StartTime $Message.actionRequiredByDateTime -EndTime $Script:Today
31 | [PSCustomObject] @{
32 | Id = $Message.Id
33 | Title = $Message.Title
34 | Service = $Message.services
35 | LastUpdatedTime = if ($Message.lastModifiedDateTime) { [DateTime]::Parse($Message.lastModifiedDateTime) } else { $null }
36 | LastUpdatedDays = Convert-TimeToDays -StartTime $Message.lastModifiedDateTime -EndTime $Script:Today
37 | ActionRequiredByDateTime = if ($Message.actionRequiredByDateTime) { [DateTime]::Parse($Message.actionRequiredByDateTime) } else { $null }
38 | ActionRequiredDays = if ($ActionRequiredDays -eq 0) { $null } else { - $ActionRequiredDays }
39 | Tags = $Message.Tags
40 | Bloglink = ($Message.details | Where-Object { $_.name -eq 'bloglink' }).Value
41 | RoadmapId = ($Message.details | Where-Object { $_.name -eq 'roadmapids' }).Value
42 | RoadmapIdLinks = ($Message.details | Where-Object { $_.name -eq 'roadmapids' }).Value | ForEach-Object {
43 | "https://www.microsoft.com/en-us/microsoft-365/roadmap?filters=&searchterms=$_"
44 | }
45 | Category = $Message.category
46 | IsMajorChange = $Message.isMajorChange
47 | Severity = $Message.Severity
48 | StartTime = If ($Message.startDateTime) { [DateTime]::Parse($Message.startDateTime) } else { $null }
49 | EndTime = if ($Message.endDateTime) { [DateTime]::Parse($Message.endDateTime) } else { $null }
50 | Message = $Message.body.content
51 | }
52 | }
53 | $Output
54 | }
--------------------------------------------------------------------------------
/Private/Get-Office365ServiceHealthServices.ps1:
--------------------------------------------------------------------------------
1 | function Get-Office365ServiceHealthServices {
2 | [CmdLetbinding()]
3 | param(
4 | [System.Collections.IDictionary] $Authorization,
5 | [string] $TenantDomain
6 | )
7 | try {
8 | $Services = Invoke-Graphimo -Uri "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews" -Method GET -Headers $Authorization -FullUri
9 | } catch {
10 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
11 | Write-Warning -Message "Get-Office365ServiceHealthServices - Error: $ErrorMessage"
12 | return
13 | }
14 | $Output = @{ }
15 | $Output.Simple = foreach ($Service in $Services) {
16 | [PSCustomObject][ordered] @{
17 | ID = $Service.ID
18 | Service = $Service.service
19 | }
20 | }
21 | return $Output
22 | }
23 |
--------------------------------------------------------------------------------
/Public/Get-Office365Health.ps1:
--------------------------------------------------------------------------------
1 | function Get-Office365Health {
2 | [CmdLetbinding()]
3 | param(
4 | [string][alias('ClientID')] $ApplicationID,
5 | [string][alias('ClientSecret')] $ApplicationKey,
6 | [string] $TenantDomain,
7 | [PSWinDocumentation.Office365Health[]] $TypesRequired = [PSWinDocumentation.Office365Health]::All,
8 | [switch] $ToLocalTime
9 | )
10 | $StartTime = Start-TimeLog
11 | try {
12 | $Script:TimeZoneBias = (Get-TimeZone -ErrorAction Stop).BaseUtcOffset.TotalMinutes
13 | } catch {
14 | Write-Warning "ConvertFrom-UTCTime - couldn't get timezone. Please report on GitHub."
15 | $Script:TimeZoneBias = 0
16 | }
17 | $Script:Today = Get-Date
18 | if ($null -eq $TypesRequired -or $TypesRequired -contains [PSWinDocumentation.Office365Health]::All) {
19 | $TypesRequired = Get-Types -Types ([PSWinDocumentation.Office365Health])
20 | }
21 | $Authorization = Connect-O365ServiceHealth -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain
22 | if ($null -eq $Authorization) {
23 | return
24 | }
25 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::Services)) {
26 | $Services = Get-Office365ServiceHealthServices -Authorization $Authorization -TenantDomain $TenantDomain
27 | }
28 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @(
29 | [PSWinDocumentation.Office365Health]::CurrentStatus,
30 | [PSWinDocumentation.Office365Health]::CurrentStatusExtended
31 | )) {
32 | $CurrentStatus = Get-Office365ServiceHealthCurrentStatus -Authorization $Authorization -TenantDomain $TenantDomain -ToLocalTime:$ToLocalTime
33 | }
34 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @(
35 | [PSWinDocumentation.Office365Health]::Incidents,
36 | [PSWinDocumentation.Office365Health]::IncidentsExtended
37 | [PSWinDocumentation.Office365Health]::IncidentsUpdates
38 | )) {
39 | $Issues = Get-Office365ServiceHealthIssues -Authorization $Authorization -ToLocalTime:$ToLocalTime
40 | }
41 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @(
42 | [PSWinDocumentation.Office365Health]::MessageCenterInformation,
43 | [PSWinDocumentation.Office365Health]::MessageCenterInformationExtended
44 | )) {
45 | $Messages = Get-Office365ServiceHealthMessages -Authorization $Authorization
46 | }
47 | $Output = [ordered] @{}
48 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::Services)) {
49 | $Output.Services = $Services.Simple
50 | }
51 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::CurrentStatus)) {
52 | $Output.CurrentStatus = $CurrentStatus.Simple
53 | }
54 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::CurrentStatusExtended)) {
55 | $Output.CurrentStatusExtended = $CurrentStatus.Extended
56 | }
57 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::MessageCenterInformation)) {
58 | $Output.MessageCenterInformation = $Messages.MessageCenterInformation | Sort-Object -Property LastUpdatedTime -Descending
59 | }
60 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::MessageCenterInformationExtended)) {
61 | $Output.MessageCenterInformationExtended = $Messages.MessageCenterInformationExtended | Sort-Object -Property LastUpdatedTime -Descending
62 | }
63 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::Incidents)) {
64 | $Output.Incidents = $Issues.Incidents | Sort-Object -Property LastUpdatedTime -Descending
65 | }
66 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::IncidentsExtended)) {
67 | $Output.IncidentsExtended = $Issues.IncidentsExtended | Sort-Object -Property LastUpdatedTime -Descending
68 | }
69 | if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.Office365Health]::IncidentsUpdates)) {
70 | $Output.IncidentsUpdates = $Issues.IncidentsUpdates | Sort-Object -Property LastUpdatedTime -Descending
71 | }
72 | $EndTime = Stop-TimeLog -Time $StartTime -Option OneLiner
73 | Write-Verbose "Get-Office365Health - Time to process: $EndTime"
74 | return $Output
75 | }
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | # PSWinDocumentation.O365HealthService - PowerShell Module
25 |
26 | `PSWinDocumentation.O365HealthService` is a Powershell module that has a single goal of getting Office 365 Health Status
27 |
28 | ## Overview
29 |
30 | - How to/What it really use and how you can use it: https://evotec.xyz/powershell-way-to-get-all-information-about-office-365-service-health/
31 | - Step by Step to Get App ID and App Key: https://evotec.xyz/preparing-azure-app-registrations-permissions-for-office-365-health-service/
32 |
33 | ### Required Permissions
34 |
35 | Please not that Microsoft deprecates the old way of accessing Service Health API. Since version 1.0+ you need to modify permissions for it to work properly.
36 |
37 | 
38 |
39 | ### Install
40 |
41 | ```powershell
42 | Install-Module PSWinDocumentation.O365HealthService -Force
43 | ```
44 |
45 |
46 | ### Example 1
47 |
48 | Here's a live demo generated using Dashimo: https://evotec.xyz/wp-content/uploads/2019/05/Health.html
49 |
50 | ```powershell
51 | Import-Module PSWinDocumentation.O365HealthService -Force
52 | Import-Module PSWriteHTML -Force
53 |
54 | $ApplicationID = ''
55 | $ApplicationKey = ''
56 | $TenantDomain = 'evotec.pl' # CustomDomain (onmicrosoft.com won't work), alternatively you can use DirectoryID
57 |
58 | $O365 = Get-Office365Health -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain -Verbose
59 |
60 | Dashboard -FilePath $PSScriptRoot\Health.html {
61 | TabOption -BorderRadius 0px -BackgroundColorActive DimGrey
62 | SectionOption -BorderRadius 0px -HeaderBackGroundColor DimGrey
63 | TableOption -DataStore JavaScript -ArrayJoinString "; " -ArrayJoin -BoolAsString
64 | Tab -Name 'Services' {
65 | Section -Name 'Service List' {
66 | Table -DataTable $O365.Services -Filtering
67 | }
68 | }
69 | Tab -Name 'Current Status' {
70 | Section -Invisible {
71 | Section -Name 'Current Status' {
72 | Table -DataTable $O365.CurrentStatus {
73 | TableCondition -Name 'ServiceStatus' -Value 'serviceOperational' -BackgroundColor MintGreen -FailBackgroundColor Salmon
74 | } -Filtering
75 | }
76 | Section -Name 'Current Status Extended' {
77 | Table -DataTable $O365.CurrentStatusExtended {
78 | TableCondition -Name 'ServiceStatus' -Value 'serviceOperational' -BackgroundColor MintGreen -FailBackgroundColor Salmon
79 | } -Filtering
80 | }
81 | }
82 | }
83 | Tab -Name 'Message Center Information' {
84 | #Section -Invisible {
85 | Section -Name 'Message Center' {
86 | Table -DataTable $O365.MessageCenterInformation -Filtering
87 | }
88 | Section -Name 'Message Center Extended' {
89 | Table -DataTable $O365.MessageCenterInformationExtended -InvokeHTMLTags -Filtering
90 | }
91 | #}
92 | }
93 | Tab -Name 'Incidents' {
94 | Section -Invisible {
95 | Section -Name 'Incidents' {
96 | Table -DataTable $O365.Incidents -Filtering {
97 | TableCondition -Name 'IsResolved' -Value $true -BackgroundColor MintGreen -FailBackgroundColor Salmon -ComparisonType bool
98 | }
99 | }
100 | Section -Name 'Incidents Extended' {
101 | Table -DataTable $O365.IncidentsExtended -Filtering {
102 | TableCondition -Name 'IsResolved' -Value $true -BackgroundColor MintGreen -FailBackgroundColor Salmon -ComparisonType bool
103 | }
104 | }
105 | }
106 | Section -Name 'Incidents Messages' {
107 | Table -DataTable $O365.IncidentsUpdates -InvokeHTMLTags -Filtering
108 | }
109 | }
110 | } -Online -ShowHTML
111 | ```
112 |
113 | ### Example 2
114 |
115 | ``` PowerShell
116 | Import-Module PSWinDocumentation.O365HealthService -Force
117 |
118 | $ApplicationID = ''
119 | $ApplicationKey = ''
120 | $TenantDomain = 'evotec.pl' # CustomDomain (onmicrosoft.com won't work), alternatively you can use DirectoryID
121 |
122 | $O365 = Get-Office365Health -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain -Verbose
123 | $O365.CurrentStatus | Format-Table -AutoSize
124 |
125 | ```
126 |
127 | Output:
128 |
129 | ```
130 | Service ServiceStatus StatusTime IncidentIds
131 | ------- ------------- ---------- -----------
132 | Exchange Online Restoring service 21.04.2019 16:54:19 EX177902
133 | Microsoft Kaizala Normal service 21.04.2019 16:54:19
134 | Skype for Business Service degradation 21.04.2019 16:54:19 LY177449
135 | Microsoft Teams Normal service 21.04.2019 16:54:19
136 | Mobile Device Management for Office 365 Normal service 21.04.2019 16:54:19
137 | Office Online Normal service 21.04.2019 16:54:19
138 | OneDrive for Business Normal service 21.04.2019 16:54:19
139 | Identity Service Normal service 21.04.2019 16:54:19
140 | Office 365 Portal Normal service 21.04.2019 16:54:19
141 | Planner Normal service 21.04.2019 16:54:19
142 | SharePoint Online Normal service 21.04.2019 16:54:19
143 | Microsoft StaffHub Normal service 21.04.2019 16:54:19
144 | Sway Normal service 21.04.2019 16:54:19
145 | Yammer Enterprise Normal service 21.04.2019 16:54:19
146 | ```
147 |
148 | ### Example 3
149 |
150 |
151 | ``` PowerShell
152 | Import-Module PSWinDocumentation.O365HealthService -Force
153 |
154 | $ApplicationID = ''
155 | $ApplicationKey = ''
156 | $TenantDomain = 'evotec.pl' # CustomDomain (onmicrosoft.com won't work), alternatively you can use DirectoryID
157 |
158 | $O365 = Get-Office365Health -ApplicationID $ApplicationID -ApplicationKey $ApplicationKey -TenantDomain $TenantDomain -Verbose
159 | $O365.CurrentStatus | Format-Table -AutoSize
160 |
161 | ```
162 |
163 | Output:
164 |
165 | ```
166 |
167 | ID Service ServiceStatus StatusTime Incidents
168 | -- ------- ------------- ---------- ---------
169 | Exchange Exchange Online serviceDegradation 29.01.2022 21:14:47 {EX316072, EX316697}
170 | OrgLiveID Identity Service serviceOperational 29.01.2022 21:14:47
171 | OSDPPlatform Microsoft 365 suite serviceOperational 29.01.2022 21:14:47
172 | Lync Skype for Business serviceOperational 29.01.2022 21:14:47
173 | SharePoint SharePoint Online serviceOperational 29.01.2022 21:14:47
174 | DynamicsCRM Dynamics 365 Apps serviceOperational 29.01.2022 21:14:47
175 | RMS Azure Information Protection serviceOperational 29.01.2022 21:14:47
176 | yammer Yammer Enterprise serviceOperational 29.01.2022 21:14:47
177 | MobileDeviceManagement Mobile Device Management for Office 365 serviceOperational 29.01.2022 21:14:47
178 | Planner Planner serviceOperational 29.01.2022 21:14:47
179 | SwayEnterprise Sway serviceOperational 29.01.2022 21:14:47
180 | PowerBIcom Power BI serviceOperational 29.01.2022 21:14:47
181 | Intune Microsoft Intune serviceOperational 29.01.2022 21:14:47
182 | OneDriveForBusiness OneDrive for Business serviceOperational 29.01.2022 21:14:47
183 | microsoftteams Microsoft Teams serviceOperational 29.01.2022 21:14:47
184 | StaffHub Microsoft StaffHub serviceOperational 29.01.2022 21:14:47
185 | kaizalamessagingservices Microsoft Kaizala serviceOperational 29.01.2022 21:14:47
186 | Bookings Microsoft Bookings serviceOperational 29.01.2022 21:14:47
187 | officeonline Office for the web serviceOperational 29.01.2022 21:14:47
188 | O365Client Microsoft 365 Apps serviceOperational 29.01.2022 21:14:47
189 | PowerAppsM365 Power Apps in Microsoft 365 serviceOperational 29.01.2022 21:14:47
190 | MicrosoftFlow Microsoft Power Automate serviceOperational 29.01.2022 21:14:47
191 | MicrosoftFlowM365 Microsoft Power Automate in Microsoft 365 serviceOperational 29.01.2022 21:14:47
192 | Forms Microsoft Forms serviceOperational 29.01.2022 21:14:47
193 | Microsoft365Defender Microsoft 365 Defender serviceOperational 29.01.2022 21:14:47
194 | Stream Microsoft Stream serviceOperational 29.01.2022 21:14:47
195 | Viva Microsoft Viva serviceOperational 29.01.2022 21:14:47
196 | cloudappsecurity Microsoft Defender for Cloud Apps serviceOperational 29.01.2022 21:14:47
197 | ```
--------------------------------------------------------------------------------