<# M365 Analytics Log Collector #> #Requires -RunAsAdministrator #---------------------------------------------------------------------------------------------------------- # # Parameter Declarations # #---------------------------------------------------------------------------------------------------------- Param( # File share to store logs, the maximum length is 130 since the script would create sub folders and files [Parameter(Position=1)] [string]$LogPath, # LogMode == 0 log to console only # LogMode == 1 log to file and console # LogMode == 2 log to file only [Parameter(Position=2)] [Int16]$LogMode = 1, # CollectNetTrace == 0 to disable collect Net Trace, otherwise enable collect Net Trace. [Parameter(Position=3)] [Int16]$CollectNetTrace = 0, # CollectUTCTrace == 0 to disable collect UTC Trace, otherwise enable collect UTC Trace. [Parameter(Position=4)] [Int16]$CollectUTCTrace = 0 ) #---------------------------------------------------------------------------------------------------------- # # Startup # #---------------------------------------------------------------------------------------------------------- # Make sure we are running x64 PS on 64-bit OS. If not then start a x64 process of PowerShell $powerShellHome = $PSHOME.ToLower() if ([System.Environment]::Is64BitOperatingSystem -eq $true) { if ([System.Environment]::Is64BitProcess -eq $false) { Write-Verbose "Launching x64 PowerShell" $powerShellHome = $powerShellHome.Replace('syswow64','sysnative') &"$powerShellHome\powershell.exe" -ExecutionPolicy AllSigned -NonInteractive -NoProfile $myInvocation.Line exit $lastexistcode } } #---------------------------------------------------------------------------------------------------------- # # Parameter Intialization and Validation # #---------------------------------------------------------------------------------------------------------- # Parameter: $LogPath if([String]::IsNullOrEmpty($LogPath) -or [String]::IsNullOrWhiteSpace($LogPath)) { # Set to default value $LogPath = "$Env:SystemDrive\M365AnalyticsLogs" } else { Write-Verbose "Validating path length no more than 130: $LogPath" $LogPath = $LogPath.Trim().TrimEnd('\') if($LogPath.Length -gt 130) { throw "Failed to validate the length of the given path: $LogPath" } # Validate parameter: $LogPath Write-Verbose "Validating path format: $LogPath" $validateResult = $false if((Test-Path $LogPath -IsValid) -eq $true) { $testSplitArray = $LogPath.Split(':') if($testSplitArray.Count -eq 1) { $validateResult = $true } elseif($testSplitArray.Count -eq 2) { $targetDrv = Get-PSDrive -Name $testSplitArray[0] if($targetDrv -ne $null) { $fileDrv = Get-PSProvider -PSProvider FileSystem if($fileDrv -ne $null) { if($fileDrv.Drives.Contains($targetDrv) -eq $true) { $validateResult = $true } } } } } if($validateResult -eq $false) { throw "Failed to validate the format of the given path: $LogPath" } } Write-Verbose "Output Path = $LogPath" # Parameter: $LogMode Write-Verbose "Validating log mode(0|1|2): $LogMode" if(($LogMode -ne 0) -and ($LogMode -ne 1) -and ($LogMode -ne 2)) { throw "Failed to validate the given log mode: $LogMode" } Write-Verbose "Log Mode = $LogMode" # Parameter: $CollectNetTrace if($CollectNetTrace -eq 0) { Write-Verbose "Collect Net Trace = No" } else { Write-Verbose "Collect Net Trace = Yes" } # Parameter: $CollectUTCTrace if($CollectUTCTrace -eq 0) { Write-Verbose "Collect UTC Trace = No" } else { Write-Verbose "Collect UTC Trace = Yes" } #---------------------------------------------------------------------------------------------------------- # # Global Variables # #---------------------------------------------------------------------------------------------------------- # Temporary file to store providers $global:tempProviderFile = [System.IO.Path]::GetTempFileName() # Providers info $global:providersText = @" {43ac453b-97cd-4b51-4376-db7c9bb963ac} 0 255 {56DC463B-97E8-4B59-E836-AB7C9BB96301} 0 255 "@ # Script folder root $global:scriptRoot = Split-Path -Path $MyInvocation.MyCommand.Path # Set the exit code to the first exception exit code $global:errorCode = [string]::Empty; # Total error count while running the script [int]$global:errorCount = 0; # OS version $global:osVersion = (Get-WmiObject Win32_OperatingSystem).Version # OS name $global:operatingSystemName = (Get-WmiObject Win32_OperatingSystem).Name # OS Architecture $global:osArchitecture = $ENV:Processor_Architecture # Global utc trace name $global:timeStart=Get-Date $global:timeStartString=$global:timeStart.ToString("yy_MM_dd_HH_mm_ss") $global:utcTraceName = "utctrace" + $global:timeStartString #---------------------------------------------------------------------------------------------------------------- # # Main # #---------------------------------------------------------------------------------------------------------------- $main = { Try { # Initialize provider file InitializeProviderFile # Quit if System variable WINDIR is not set Try { $global:windir=[System.Environment]::ExpandEnvironmentVariables("%WINDIR%") } Catch { $exceptionDetails = "Exception: " + $_.Exception.Message + "HResult: " + $_.Exception.HResult Write-Error "Failure finding system variable WINDIR. $exceptionDetails Error 23" [System.Environment]::Exit(23) } # Get Sqm Machine Id Get-SqmID # Get ConfigMgr Client Version Get-CmClientVersion # Create the log file if logMode requires logging to file. CreateLogFile Log "Starting M365AnalyticsLogsCollector" Log "UTC DateTime: $global:utcDate" Log "OS: $global:osVersion" Log "Architecture: $global:osArchitecture" Log "Machine Sqm Id: $global:sClientId" Log "Configuration Manager Client Version: $global:smsClientVersion" # Sets VerboseMode to enable appraiser logging value to the registry SetAppraiserVerboseMode # Sets RequestAllAppraiserVersions key if($global:osBuildNumber -lt 10240) { SetRequestAllAppraiserVersions } if($CollectNetTrace -ne 0) { # Start Netsh trace StartNetworkTrace } if($CollectUTCTrace -ne 0) { #Start UTC trace StartUTCTrace } # restart Diagtrack service RestartDiagtrack # Run Connectivity Tool RunConnectivityDiagnosis # Run Census RunCensus if($CollectNetTrace -ne 0) { # Stop Netsh trace StopNetworkTrace } if($CollectUTCTrace -ne 0) { # Stop UTC trace StopUTCTrace } # Run Appraiser RunAppraiser # Collect the logs Try { Log "Running diagnose_internal to collect logs" DiagnoseInternal $global:logFolder } Catch { Log "diagnose_internal failed with unexpected exception" "Error" "37" "diagnose_internal" $_.Exception.HResult $_.Exception.Message } # Collect M365AHandler logs CollectM365AHandlerLog if($global:errorCount -eq 0) { Log "Script finished successfully" Exit(0) } } Catch { Log "Unexpected error occured while executing the script" "Error" "1" "UnExpectedException" $_.Exception.HResult $_.Exception.Message Log "Script failed" "Failure" "1" "ScriptEnd" [System.Environment]::Exit(1) } Finally { # Disable appriaser verbose mode after running the appriaser DisableAppraiserVerboseMode # Restart Diagtrack service RestartDiagtrack # Cleanup temporary file Remove-Item -Path $global:tempProviderFile } } #---------------------------------------------------------------------------------------------------------- # # Function Definitions # #---------------------------------------------------------------------------------------------------------- function InitializeProviderFile { $global:providersText | Out-File $global:tempProviderFile -Append -Encoding ascii } function DiagnoseInternal($diaLogPath) { if ((test-path $diaLogPath) -eq $false) { New-Item -ItemType Directory -Path $diaLogPath -Force | Out-Null } Get-WmiObject -Query 'select * from win32_quickfixengineering' | sort hotfixid | Out-File "$diaLogPath\installedKBs.txt" -Force ROBOCOPY "$env:windir\appcompat" "$diaLogPath\appcompat" *.* /E /XF *.hve* /R:1 | Out-Null regedit /e "$diaLogPath\RegAppCompatFlags.txt" "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags" regedit /e "$diaLogPath\RegCensus.txt" "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Census" regedit /e "$diaLogPath\RegSQM.txt" "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQMClient" regedit /e "$diaLogPath\RegDiagTrack.txt" "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Diagnostics\DiagTrack" regedit /e "$diaLogPath\RegPoliciesDataCollection.txt" "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" regedit /e "$diaLogPath\RegDataCollection.txt" "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DataCollection" } function Get-SqmID { Try { $sqmID = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\SQMClient -Name MachineId).MachineId $global:sClientId = "s:" + $sqmID.Substring(1).Replace("}", "") } Catch { $hexHresult = "{0:X}" -f $_.Exception.HResult $exceptionMessage = $_.Exception.Message Write-Error "Get-SqmID failed with unexpected exception.`nException: $exceptionMessage HResult: 0x$hexHresult" [System.Environment]::Exit(38) } } function Get-CmClientVersion { try { $propertyPath = "HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client" $propertyName = "SmsClientVersion" if (Test-Path -Path $propertyPath) { $property = Get-ItemProperty -Path $propertyPath -Name $propertyName -ErrorAction SilentlyContinue if ($null -eq $property) { Log "Get-CmClientVersion: Could not find registry value $propertyName at path $propertyPath" "Warning" } else { $global:smsClientVersion = $property.SmsClientVersion } } else { Log "Get-CmClientVersion: Could not find registry key $propertyPath" "Warning" } } catch { Log "Get-CmClientVersion: Error getting $propertyName registry value at path $propertyPath" "Warning" $null "Get-CmClientVersion" $_.Exception.HResult $_.Exception.Message } } function CreateLogFile { Write-Verbose "Creating output folder" $timeStart=Get-Date $timeStartString=$timeStart.ToString("yy_MM_dd_HH_mm_ss") $logFolderName = "M365AnalyticsLogs_" + $timeStartString $global:logFolder = $logPath +"\"+$logFolderName Try { $outputFolder = New-Item $global:logFolder -type directory Write-Host "Output folder created successfully: $outputFolder" } Catch { $hexHresult = "{0:X}" -f $_.Exception.HResult $exceptionMessage = $_.Exception.Message Write-Error "Could not create output folder at the given logPath: $LogPath`nException: $exceptionMessage HResult: 0x$hexHresult" [System.Environment]::Exit(28) } if($LogMode -ne 0) { Write-Verbose "Creating Log File" $fileName = $logFolderName+".txt" $global:logFile=$global:logFolder+"\"+$fileName Try { New-Item $global:logFile -type file | Out-Null Write-Verbose "Log File created successfully: $global:logFile" } Catch { $hexHresult = "{0:X}" -f $_.Exception.HResult $exceptionMessage = $_.Exception.Message Write-Error "Could not create log file at the given logPath: $LogPath`nException: $exceptionMessage HResult: 0x$hexHresult" [System.Environment]::Exit(28) } } } function StartNetworkTrace { Try { Log "Start: StartNetworkTrace" netsh trace start capture=yes scenario=InternetClient provider=Microsoft-Windows-CAPI2 traceFile="$global:logFolder\nettrace.etl" | Out-Null Log "Passed: StartNetworkTrace" } Catch { Log "StartNetworkTrace failed with an unexpected exception." "Error" "2001" "StartNetworkTrace" $_.Exception.HResult $_.Exception.Message } } function StartUTCTrace { Try { Log "Start: StartUTCTrace" $logmanFolder = $null if($global:osArchitecture.contains("64")) { $logmanFolder = "$global:windir\system32\" } else { $logmanFolder = "$global:windir\system32\" } & logman start $global:utcTraceName -pf "$global:tempProviderFile" -bs 32768 -nb 128 -ets -o "$global:logFolder\DAUTCtrace.etl" | Out-Null Log "Passed: StartUTCTrace" } Catch { Log "StartUTCTrace failed with an unexpected exception." "Error" "2003" "StartUTCTrace" $_.Exception.HResult $_.Exception.Message } } function StopNetworkTrace { Try { Log "Start: StopNetworkTrace" netsh trace stop | Out-Null Log "Passed: StopNetworkTrace" } Catch { Log "StopNetworkTrace failed with an unexpected exception." "Error" "2002" "StopNetworkTrace" $_.Exception.HResult $_.Exception.Message } } function StopUTCTrace { Try { Log "Start: StopUTCTrace" $logmanFolder = $null if($global:osArchitecture.contains("64")) { $logmanFolder = "$global:windir\system32\" } else { $logmanFolder = "$global:windir\system32\" } & logman.exe stop $global:utcTraceName -ets | Out-Null Log "Passed: StopUTCTrace" Log "Collect DownloadedSettings to log folder" & takeown -f "$Env:ProgramData\Microsoft\Diagnosis\DownloadedSettings\*" | Out-Null & icacls "$Env:ProgramData\Microsoft\Diagnosis\DownloadedSettings\*" /grant administrators:f | Out-Null New-Item $global:logFolder\DownloadedSettings -type directory | Out-Null Copy-Item "$Env:ProgramData\Microsoft\Diagnosis\DownloadedSettings\*" -Destination $global:logFolder\DownloadedSettings | Out-Null } Catch { Log "StopUTCTrace failed with an unexpected exception." "Error" "2004" "StopUTCTrace" $_.Exception.HResult $_.Exception.Message } } function RestartDiagtrack { Log "Start: RestartDiagtrack" Try { & Net stop diagtrack | Out-Null & Reg add hklm\software\microsoft\windows\currentversion\diagnostics\diagtrack\testhooks /v ResetEventStore /t REG_DWORD /d 1 /f | Out-Null & Net start diagtrack | Out-Null & Reg delete hklm\software\microsoft\windows\currentversion\diagnostics\diagtrack\testhooks /v ResetEventStore /f | Out-Null Log "Passed: RestartDiagtrack" } Catch { Log "RestartDiagtrack failed to execute - script will continue." "Warning" $null "RestartDiagtrack" $_.Exception.HResult $_.Exception.Message return } } function RunConnectivityDiagnosis { Log "Start: RunConnectivityDiagnosis" Try { $propertyPath = "HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" if(Test-Path -Path $propertyPath) { if ((Get-ItemProperty -Path $propertyPath -Name LogDirectory -ErrorAction SilentlyContinue) -eq $null) { Log "Could not find registry key LogDirectory at path HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" } else { Try { $logDirectoryKeyM365 = Get-ItemProperty -Path $propertyPath -Name LogDirectory $logDirectoryM365 = $logDirectoryKeyM365.LogDirectory $connectivitydiagnosis = $logDirectoryM365.ToString().Replace("Logs", "settingsplugins\connectivitydiagnosis.exe") if((Test-Path -Path $connectivitydiagnosis) -eq $False) { $connectivitydiagnosis = $logDirectoryM365.ToString().Replace("Logs", "connectivitydiagnosis.exe") } #Log $connectivitydiagnosis #Log $logDirectoryM365 $currentDirectory = $global:scriptRoot & cd $global:logFolder & timeout 5 | Out-Null & $connectivitydiagnosis -verbose > ConnectivityDiagnosis.txt & timeout 5 | Out-Null & cd $currentDirectory Log "Passed: RunConnectivityDiagnosis" } Catch { Log "Error running RunConnectivityDiagnosis" "Warning" $null "RunConnectivityDiagnosis" $_.Exception.HResult $_.Exception.Message return } } } } Catch { Log "Error running RunConnectivityDiagnosis" "Warning" $null "RunConnectivityDiagnosis" $_.Exception.HResult $_.Exception.Message } } function SetAppraiserVerboseMode { Log "Start: SetAppraiserVerboseMode" Try { $vAppraiserPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Appraiser" Log "Enabling Appraiser logs for debugging by setting VerboseMode property to 1 at the registry key path: $vAppraiserPath" if ((Get-ItemProperty -Path $vAppraiserPath -Name VerboseMode -ErrorAction SilentlyContinue) -eq $null) { Try { New-ItemProperty -Path $vAppraiserPath -Name VerboseMode -PropertyType DWord -Value 1 | Out-Null } Catch { Log "SetAppraiserVerboseMode failed to write the VerboseMode property at registry key $vAppraiserPath. This is not fatal, script will continue." "Warning" $null "SetAppraiserVerboseMode" $_.Exception.HResult $_.Exception.Message return } } else { Log "Appraiser verbose mode is already enabled" } Log "Enabling Appraiser logs for debugging by setting TestHooksEnabled property to 1 at the registry key path: $vAppraiserPath" if ((Get-ItemProperty -Path $vAppraiserPath -Name TestHooksEnabled -ErrorAction SilentlyContinue) -eq $null) { Try { New-ItemProperty -Path $vAppraiserPath -Name TestHooksEnabled -PropertyType DWord -Value 1 | Out-Null } Catch { Log "SetAppraiserVerboseMode failed to write the TestHooksEnabled property at registry key $vAppraiserPath. This is not fatal, script will continue." "Warning" $null "SetAppraiserVerboseMode" $_.Exception.HResult $_.Exception.Message return } } else { Log "Appraiser TestHooksEnabled property is already set" } Log "Passed: SetAppraiserVerboseMode" } Catch { Log "SetAppraiserVerboseMode failed with unexpected exception. This is not fatal, script will continue." "Warning" $null "SetAppraiserVerboseMode" $_.Exception.HResult $_.Exception.Message } } function DisableAppraiserVerboseMode { Log "Start: DisableAppraiserVerboseMode" Try { $vAppraiserPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Appraiser" if ((Get-ItemProperty -Path $vAppraiserPath -Name VerboseMode -ErrorAction SilentlyContinue) -ne $null) { Try { Remove-ItemProperty -Path $vAppraiserPath -Name VerboseMode } Catch { Log "DisableAppraiserVerboseMode failed deleting VerboseMode property at registry key path: $vAppraiserPath. This is not fatal, script will continue." "Warning" $null "DisableAppraiserVerboseMode" $_.Exception.HResult $_.Exception.Message } } else { Log "Appraiser VerboseMode key already deleted" } Log "Passed: DisableAppraiserVerboseMode" } Catch { Log "DisableAppraiserVerboseMode failed with unexpected exception. This is not fatal, script will continue." "Warning" $null "DisableAppraiserVerboseMode" $_.Exception.HResult $_.Exception.Message } } function SetRequestAllAppraiserVersions { Log "Start: SetRequestAllAppraiserVersions" Try { $propertyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" $propertyGPOPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" if(Test-Path -Path $propertyPath) { if ((Get-ItemProperty -Path $propertyPath -Name RequestAllAppraiserVersions -ErrorAction SilentlyContinue) -eq $null) { Try { New-ItemProperty -Path $propertyPath -Name RequestAllAppraiserVersions -PropertyType DWord -Value 1 | Out-Null } Catch { Log "SetRequestAllAppraiserVersions failed setting RequestAllAppraiserVersions property at registry key path: $propertyPath" "Error" "20" "SetRequestAllAppraiserVersions" $_.Exception.HResult $_.Exception.Message return } } else { Try { Set-ItemProperty -Path $propertyPath -Name RequestAllAppraiserVersions -Value 1 } Catch { Log "SetRequestAllAppraiserVersions failed setting RequestAllAppraiserVersions property at registry key path: $propertyPath" "Error" "20" "SetRequestAllAppraiserVersions" $_.Exception.HResult $_.Exception.Message return } } } if(Test-Path -Path $propertyGPOPath) { if ((Get-ItemProperty -Path $propertyGPOPath -Name RequestAllAppraiserVersions -ErrorAction SilentlyContinue) -eq $null) { Try { New-ItemProperty -Path $propertyGPOPath -Name RequestAllAppraiserVersions -PropertyType DWord -Value 1 | Out-Null } Catch { Log "SetRequestAllAppraiserVersions failed setting RequestAllAppraiserVersions property at registry key path: $propertyGPOPath" "Error" "20" "SetRequestAllAppraiserVersions" $_.Exception.HResult $_.Exception.Message return } } else { Try { Set-ItemProperty -Path $propertyPath -Name RequestAllAppraiserVersions -Value 1 } Catch { Log "SetRequestAllAppraiserVersions failed setting RequestAllAppraiserVersions property at registry key path: $propertyGPOPath" "Error" "20" "SetRequestAllAppraiserVersions" $_.Exception.HResult $_.Exception.Message return } } } Log "Passed: SetRequestAllAppraiserVersions" } Catch { Log "SetRequestAllAppraiserVersions failed with unexpected exception." "Error" "21" "SetRequestAllAppraiserVersions" $_.Exception.HResult $_.Exception.Message } } function RunAppraiser { Try { Log "Start: RunAppraiser" Log "Attempting to run inventory...This may take a few minutes to complete, please do not cancel the script." do { CompatTelRunner.exe -m:appraiser.dll -f:DoScheduledTelemetryRun ent | out-null $appraiserLastExitCode = $LASTEXITCODE $appraiserLastExitCodeHex = "{0:X}" -f $appraiserLastExitCode if($appraiserLastExitCode -eq 0x80070021) { Log "RunAppraiser needs to run CompatTelRunner.exe, but it is already running. Waiting for 60 seconds before retry." Start-Sleep -Seconds 60 } else { break } $NoOfAppraiserRetries = $NoOfAppraiserRetries - 1 }While($NoOfAppraiserRetries -gt 0) if ($appraiserLastExitCode -ne 0x0) { if ($appraiserLastExitCode -lt 0x0) { Log "RunAppraiser failed. CompatTelRunner.exe exited with last error code: 0x$appraiserLastExitCodeHex." "Error" "33" "RunAppraiser" "0x$appraiserLastExitCodeHex" "CompatTelRunner.exe returned with an error code." } else { Log "RunAppraiser succeeded with a return code: 0x$appraiserLastExitCodeHex." } } else { Log "Passed: RunAppraiser" } } Catch { Log "RunAppraiser failed with unexpected exception." "Error" "22" "RunAppraiser" $_.Exception.HResult $_.Exception.Message } } function RunCensus { Log "Start: RunCensus" Try { $censusRunRegKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Census" if($(Test-Path $censusRunRegKey) -eq $false) { New-Item -Path $censusRunRegKey -ItemType Key | Out-Null } # Turn Census FullSync mode on Log "Setting property: FullSync to value 1 at registry key path $censusRunRegKey to turn on Census FullSync mode" if ((Get-ItemProperty -Path $censusRunRegKey -Name FullSync -ErrorAction SilentlyContinue) -eq $null) { New-ItemProperty -Path $censusRunRegKey -Name FullSync -PropertyType DWord -Value 1 | Out-Null } else { Set-ItemProperty -Path $censusRunRegKey -Name FullSync -Value 1 } # Run Census and validate the run # Census invocation commands are different for Windows 10 and Downlevel [int] $runCounterBefore = (Get-ItemProperty -Path $censusRunRegKey).RunCounter if($runCounterBefore -eq $null) { New-ItemProperty -Path $censusRunRegKey -Name RunCounter -PropertyType DWord -Value 0 | Out-Null } if($global:operatingSystemName.ToLower().Contains("windows 10")) { $censusExe = "$global:windir\system32\devicecensus.exe" if(Test-Path -Path $censusExe) { Log "Running $censusExe" & $censusExe | Out-Null } else { Log "$censusExe path not found" "Error" "52" "RunCensus" return } } else { CompatTelRunner.exe -m:generaltel.dll -f:DoCensusRun | Out-Null } [int] $runCounterAfter = (Get-ItemProperty -Path $censusRunRegKey).RunCounter $returnCode = (Get-ItemProperty -Path $censusRunRegKey).ReturnCode $startTime = Get-Date (Get-ItemProperty -Path $censusRunRegKey).StartTime $endTime = Get-Date (Get-ItemProperty -Path $censusRunRegKey).EndTime if($returnCode -eq 0) { if($runCounterAfter -gt $runCounterBefore -and $endTime -gt $startTime) { Log "Passed: RunCensus" } else { Log "Census did not run correctly. Registray data at $censusRunRegKey are: RunCounter Before trying to run Census:$runCounterBefore, RunCounter after trying to run Census:$runCounterAfter, ReturnCode:$returnCode, UTC StartTime:$startTime, UTC EndTime:$endTime" "Warning" $null "RunCensus" } } else { Log "Census returned a non zero ReturnCode:$returnCode" "Warning" $null "RunCensus" } # Turn Census FullSync mode off Log "Resetting property: FullSync to value 0 at registry key path $censusRunRegKey to turn off Census FullSync mode" Set-ItemProperty -Path $censusRunRegKey -Name FullSync -Value 0 } Catch { Log "RunCensus failed with unexpected exception" "Error" "51" "RunCensus" $_.Exception.HResult $_.Exception.Message } } function CollectM365AHandlerLog { Log "Start: CollectM365AHandlerLog" Try { $propertyPath = "HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" if(Test-Path -Path $propertyPath) { if ((Get-ItemProperty -Path $propertyPath -Name LogDirectory -ErrorAction SilentlyContinue) -eq $null) { Log "Could not find registry key LogDirectory at path HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" } else { Try { $logDirectoryKeyM365 = Get-ItemProperty -Path $propertyPath -Name LogDirectory $logDirectoryM365 = $logDirectoryKeyM365.LogDirectory Copy-Item "$logDirectoryM365\M365AHandler.log" -Destination $global:logFolder | Out-Null Log "Passed: CollectM365AHandlerLog" } Catch { Log "Error getting logs at registry key LogDirectory at path HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" "Warning" $null "CollectM365AHandlerLog" $_.Exception.HResult $_.Exception.Message return } } } } Catch { Log "Error getting logs at registry key LogDirectory at path HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" "Warning" $null "CollectM365AHandlerLog" $_.Exception.HResult $_.Exception.Message } } function Log($logMessage, $logLevel, $errorCode, $operation, $exceptionHresult, $exceptionMessage) { $global:logDate = Get-Date -Format s $global:utcDate = ((Get-Date).ToUniversalTime()).ToString("yyyy-MM-ddTHH:mm:ssZ") $logMessageForAppInsights = $logMessage if(($logLevel -eq $null) -or ($logLevel -eq [string]::Empty)) { $logLevel = "Info" } if($logLevel -eq "Error") { # check and update the errorCode (the script will exit with the first errorCode) if(($errorCode -ne $null) -and ($errorCode -ne [string]::Empty)) { if(($global:errorCode -eq $null) -or ($global:errorCode -eq [string]::Empty)) { $global:errorCode = $errorCode } $logMessage = "ErrorCode " + $errorCode + " : " + $logMessage } if($exceptionHresult -ne $null) { $logMessage = $logMessage + " HResult: " + $exceptionHresult } if($exceptionMessage -ne $null) { $logMessage = $logMessage + " ExceptionMessage: " + $exceptionMessage } $global:errorCount++ } elseif($logLevel -eq "Exception") { if($exceptionHresult -ne $null) { $logMessage = $logMessage + " HResult: " + $exceptionHresult } if($exceptionMessage -ne $null) { $logMessage = $logMessage + " ExceptionMessage: " + $exceptionMessage } } elseif($logLevel -eq "Warning") { if($exceptionHresult -ne $null) { $logMessage = $logMessage + " HResult: " + $exceptionHresult } if($exceptionMessage -ne $null) { $logMessage = $logMessage + " ExceptionMessage: " + $exceptionMessage } } if ($LogMode -eq 0) { Try { WriteLogToConsole $logLevel $logMessage } Catch { # Error when logging to console $exceptionDetails = "Exception: " + $_.Exception.Message + "HResult: " + $_.Exception.HResult $message = "Error when logging to consloe." Write-Error "$message`n$exceptionDetails" SendEventToAppInsights "logging" $message "Failure" $global:utcDate "2" $_.Exception.HResult $_.Exception.Message [System.Environment]::Exit(2) } } elseif ($LogMode -eq 1) { Try { WriteLogToConsole $logLevel $logMessage Add-Content $global:logFile "$global:logDate : $logLevel : $logMessage" } Catch { # Error when logging to console and file $exceptionDetails = "Exception: " + $_.Exception.Message + "HResult: " + $_.Exception.HResult $message = "Error when logging to consloe and file." Write-Error "$message`n$exceptionDetails" SendEventToAppInsights "logging" $message "Failure" $global:utcDate "3" $_.Exception.HResult $_.Exception.Message [System.Environment]::Exit(3) } } elseif ($LogMode -eq 2) { Try { Add-Content $global:logFile "$global:logDate : $logLevel : $logMessage" } Catch { # Error when logging to file $exceptionDetails = "Exception: " + $_.Exception.Message + "HResult: " + $_.Exception.HResult $message = "Error when logging to file." Write-Error "$message`n$exceptionDetails" SendEventToAppInsights "logging" $message "Failure" $global:utcDate "4" $_.Exception.HResult $_.Exception.Message [System.Environment]::Exit(4) } } else { Try { WriteLogToConsole $logLevel $logMessage Add-Content $global:logFile "$global:logDate : $logLevel : $logMessage" } Catch { # Error when logging to console and file $exceptionDetails = "Exception: " + $_.Exception.Message + "HResult: " + $_.Exception.HResult $message = "Error when logging to consloe and file." Write-Error "$message`n$exceptionDetails" SendEventToAppInsights "logging" $message "Failure" $global:utcDate "5" $_.Exception.HResult $_.Exception.Message [System.Environment]::Exit(5) } } } function WriteLogToConsole($logLevel, $logMessage) { switch ($logLevel) { "Error" { Write-Error "$global:logDate : $logMessage"; Break } "Exception" { Write-Error "$global:logDate : $logMessage"; Break } "Warning" { Write-Warning "$global:logDate : $logMessage"; Break } default { Write-Host "$global:logDate : $logMessage"; Break } } } # Calling the main function &$main # SIG # Begin signature block # MIIoAgYJKoZIhvcNAQcCoIIn8zCCJ+8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBIE+lkqmSnrxsW # 2upP9cl3n3z3Xa6n76xQ00V6M5n8n6CCDYUwggYDMIID66ADAgECAhMzAAADri01 # UchTj1UdAAAAAAOuMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwODU5WhcNMjQxMTE0MTkwODU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQD0IPymNjfDEKg+YyE6SjDvJwKW1+pieqTjAY0CnOHZ1Nj5irGjNZPMlQ4HfxXG # yAVCZcEWE4x2sZgam872R1s0+TAelOtbqFmoW4suJHAYoTHhkznNVKpscm5fZ899 # QnReZv5WtWwbD8HAFXbPPStW2JKCqPcZ54Y6wbuWV9bKtKPImqbkMcTejTgEAj82 # 6GQc6/Th66Koka8cUIvz59e/IP04DGrh9wkq2jIFvQ8EDegw1B4KyJTIs76+hmpV # M5SwBZjRs3liOQrierkNVo11WuujB3kBf2CbPoP9MlOyyezqkMIbTRj4OHeKlamd # WaSFhwHLJRIQpfc8sLwOSIBBAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhx/vdKmXhwc4WiWXbsf0I53h8T8w # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMTgzNjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AGrJYDUS7s8o0yNprGXRXuAnRcHKxSjFmW4wclcUTYsQZkhnbMwthWM6cAYb/h2W # 5GNKtlmj/y/CThe3y/o0EH2h+jwfU/9eJ0fK1ZO/2WD0xi777qU+a7l8KjMPdwjY # 0tk9bYEGEZfYPRHy1AGPQVuZlG4i5ymJDsMrcIcqV8pxzsw/yk/O4y/nlOjHz4oV # APU0br5t9tgD8E08GSDi3I6H57Ftod9w26h0MlQiOr10Xqhr5iPLS7SlQwj8HW37 # ybqsmjQpKhmWul6xiXSNGGm36GarHy4Q1egYlxhlUnk3ZKSr3QtWIo1GGL03hT57 # xzjL25fKiZQX/q+II8nuG5M0Qmjvl6Egltr4hZ3e3FQRzRHfLoNPq3ELpxbWdH8t # Nuj0j/x9Crnfwbki8n57mJKI5JVWRWTSLmbTcDDLkTZlJLg9V1BIJwXGY3i2kR9i # 5HsADL8YlW0gMWVSlKB1eiSlK6LmFi0rVH16dde+j5T/EaQtFz6qngN7d1lvO7uk # 6rtX+MLKG4LDRsQgBTi6sIYiKntMjoYFHMPvI/OMUip5ljtLitVbkFGfagSqmbxK # 7rJMhC8wiTzHanBg1Rrbff1niBbnFbbV4UDmYumjs1FIpFCazk6AADXxoKCo5TsO # zSHqr9gHgGYQC2hMyX9MGLIpowYCURx3L7kUiGbOiMwaMIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGdMwghnPAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAOuLTVRyFOPVR0AAAAA # A64wDQYJYIZIAWUDBAIBBQCggd4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIMK3 # faqKQD4G7qVdjnlYCcOT7ptJNIWBvSzhUCNnblNkMHIGCisGAQQBgjcCAQwxZDBi # oESAQgBEAGUAcwBrAHQAbwBwAEEAbgBhAGwAeQB0AGkAYwBzAEwAbwBnAHMAQwBv # AGwAbABlAGMAdABvAHIALgBwAHMAMaEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAzypMT9O9UC3+hJ4aqyj63LA4eG1yjOHc/Y2J # OtqortoqXycVSI8rjfLYH9xu84U77YschS9f5nPEGfXhgf2dcMNbpva0ANbOMytn # rMKEhWgz8WZeWhiKOskP6rRil365jjrEzaw3xXQIsvoaEys5+WzKd/pVMTX3HMms # vDemXn/JPnXLQGPovGw8md8AtyM+Zo53pvVpu6ZJf7czXQpRXeLz12QIE9m+uY78 # 1RfJFg2R2kn1zkAedPPsVL5szITAY8t8oUjZyEd71xTw22rkD6ak0rgcgPiBNTC9 # hINCJHV0pdcQs3wt4X02Mc1+X7au7GDhBuQy3HLAPNFzrOjeDqGCFy0wghcpBgor # BgEEAYI3AwMBMYIXGTCCFxUGCSqGSIb3DQEHAqCCFwYwghcCAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCChl/7qbI6omZ+csG323sGjozGE77HHxLRe # Xw+WY9dnOAIGZjOhcVduGBMyMDI0MDUwMjIwNTU1Mi40NTVaMASAAgH0oIHYpIHV # MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT # HVRoYWxlcyBUU1MgRVNOOjJBRDQtNEI5Mi1GQTAxMSUwIwYDVQQDExxNaWNyb3Nv # ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIRfDCCBycwggUPoAMCAQICEzMAAAHenkie # lp8oRD0AAQAAAd4wDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg # UENBIDIwMTAwHhcNMjMxMDEyMTkwNzEyWhcNMjUwMTEwMTkwNzEyWjCB0jELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z # b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg # VFNTIEVTTjoyQUQ0LTRCOTItRkEwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt # U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALSB # 9ByF9UIDhA6xFrOniw/xsDl8sSi9rOCOXSSO4VMQjnNGAo5VHx0iijMEMH9LY2SU # IBkVQS0Ml6kR+TagkUPbaEpwjhQ1mprhRgJT/jlSnic42VDAo0en4JI6xnXoAoWo # KySY8/ROIKdpphgI7OJb4XHk1P3sX2pNZ32LDY1ktchK1/hWyPlblaXAHRu0E3yn # vwrS8/bcorANO6DjuysyS9zUmr+w3H3AEvSgs2ReuLj2pkBcfW1UPCFudLd7IPZ2 # RC4odQcEPnY12jypYPnS6yZAs0pLpq0KRFUyB1x6x6OU73sudiHON16mE0l6LLT9 # OmGo0S94Bxg3N/3aE6fUbnVoemVc7FkFLum8KkZcbQ7cOHSAWGJxdCvo5OtUtRdS # qf85FklCXIIkg4sm7nM9TktUVfO0kp6kx7mysgD0Qrxx6/5oaqnwOTWLNzK+BCi1 # G7nUD1pteuXvQp8fE1KpTjnG/1OJeehwKNNPjGt98V0BmogZTe3SxBkOeOQyLA++ # 5Hyg/L68pe+DrZoZPXJaGU/iBiFmL+ul/Oi3d83zLAHlHQmH/VGNBfRwP+ixvqhy # k/EebwuXVJY+rTyfbRfuh9n0AaMhhNxxg6tGKyZS4EAEiDxrF9mAZEy8e8rf6dlK # IX5d3aQLo9fDda1ZTOw+XAcAvj2/N3DLVGZlHnHlAgMBAAGjggFJMIIBRTAdBgNV # HQ4EFgQUazAmbxseaapgdxzK8Os+naPQEsgwHwYDVR0jBBgwFoAUn6cVXQBeYl2D # 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv # ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy # MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l # LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB # Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD # ggIBAOKUwHsXDacGOvUIgs5HDgPs0LZ1qyHS6C6wfKlLaD36tZfbWt1x+GMiazSu # y+GsxiVHzkhMW+FqK8gruLQWN/sOCX+fGUgT9LT21cRIpcZj4/ZFIvwtkBcsCz1X # EUsXYOSJUPitY7E8bbldmmhYZ29p+XQpIcsG/q+YjkqBW9mw0ru1MfxMTQs9MTDi # D28gAVGrPA3NykiSChvdqS7VX+/LcEz9Ubzto/w28WA8HOCHqBTbDRHmiP7MIj+S # QmI9VIayYsIGRjvelmNa0OvbU9CJSz/NfMEgf2NHMZUYW8KqWEjIjPfHIKxWlNMY # huWfWRSHZCKyIANA0aJL4soHQtzzZ2MnNfjYY851wHYjGgwUj/hlLRgQO5S30Zx7 # 8GqBKfylp25aOWJ/qPhC+DXM2gXajIXbl+jpGcVANwtFFujCJRdZbeH1R+Q41Fjg # Bg4m3OTFDGot5DSuVkQgjku7pOVPtldE46QlDg/2WhPpTQxXH64sP1GfkAwUtt6r # rZM/PCwRG6girYmnTRLLsicBhoYLh+EEFjVviXAGTk6pnu8jx/4WPWu0jsz7yFzg # 82/FMqCk9wK3LvyLAyDHN+FxbHAxtgwad7oLQPM0WGERdB1umPCIiYsSf/j79EqH # doNwQYROVm+ZX10RX3n6bRmAnskeNhi0wnVaeVogLMdGD+nqMIIHcTCCBVmgAwIB # AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0 # IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1 # WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O # 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn # hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t # 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq # D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP # frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW # rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv # 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb # r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten # IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc # xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a # j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB # MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU # n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw # QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E # b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB # gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/ # MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ # oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p # Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB # BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v # Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h # LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x # 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p # y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A # oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC # HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB # 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt # yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3 # rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV # v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24 # 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw # Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAtgwggJBAgEBMIIBAKGB2KSB1TCB # 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk # TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U # aGFsZXMgVFNTIEVTTjoyQUQ0LTRCOTItRkEwMTElMCMGA1UEAxMcTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAaKBSisy4y86pl8Xy # 22CJZExE2vOggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN # BgkqhkiG9w0BAQUFAAIFAOneH+MwIhgPMjAyNDA1MDIyMjIxMjNaGA8yMDI0MDUw # MzIyMjEyM1oweDA+BgorBgEEAYRZCgQBMTAwLjAKAgUA6d4f4wIBADALAgEAAgMB # HHgCAf8wBwIBAAICE/YwCgIFAOnfcWMCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYK # KwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUF # AAOBgQChqUVzyjSvZsd79JUJddw2P0vHrT2Azx/D5Nh33MUFAU0AUMRWx6pqbyHD # 7Gf0OYljwMdX8TLfsorsODpvMVFyLQQhANBQMzScn6JVYUyJWGlXEFf3zEVmoXzf # Y3wtQnrDdUVaeg9NoY9ttFqPtJamKUBRZnfPO8xtfvRBgfm8rjGCBA0wggQJAgEB # MIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB3p5InpafKEQ9 # AAEAAAHeMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcN # AQkQAQQwLwYJKoZIhvcNAQkEMSIEIEOH7oT0feHVIo2VpC5Q0ldGCYZmSyaDyjpn # TKCg8LKyMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgjj4jnw3BXhAQSQJ/ # 5gtzIK0+cP1Ns/NS2A+OB3N+HXswgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEG # A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj # cm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFt # cCBQQ0EgMjAxMAITMwAAAd6eSJ6WnyhEPQABAAAB3jAiBCCqlMZRRFgGINs4+HhX # dMQi8+rUCVp+3udHqe8NfDTWAjANBgkqhkiG9w0BAQsFAASCAgBGwl1+0uDZseka # q/ceaXwJ8/fp/4Er6cxJrm7/+0ENEAkRzho/tajjVen5+RftqjYY7tdjWw01s1xw # MEOik/nqqzCtEBqMZrGS1p67cnJBpUVpONW+inXHh7CPnOrZTQ/4olXp1UVWFczR # rs3cFyOgrtRTL1a7/EprXVFjRWXRY+dHGho/5+C46g5rp4HR2h8ucIABrbrQ880H # PC73+Nr7g30XgKkRkD2eUH/McZICsfi+7ONLvDMJQyUsZML6MwQtSm2jjWNe4gIw # 2xy1RgfaJV5w0ve9hx1MU+WcjxX7Z3M1IaG+XGxf+4FpNBczzd0BY0dY5iOSCuqp # aEDuu3DIZ9bLyN8VoFaI98plJkbba9J/nRnSRSTxbg6UoUQTiMBRLhfrEVbfGVw4 # u1ABt1mFaBX70UXhLZYYQxHG1GQnm6MSLklihtZu57yxY/VhyfH8Z3hRfAfxbyen # HpCS5AmKJpHiRSeTC2bDlfaWGOFXwcAufxXvgu+EWNgukuXKLwtT8blZv/VxuXUs # eq+YToI4oHcU9+hlFQ3+9pVH+xlppa8HJcIeqhY0WA9wMvIh4eIa97iAusIsiRh4 # xeeqxdppBFpIzQhRkK14sLggRZeJs7ayVQWTRbFyA5ZAxa9H+eJ3UA7WknMwh7g1 # vEFP+/1yvj66y7dD3Mv1nYRkpHizHQ== # SIG # End signature block