Last active
May 1, 2020 08:27
-
-
Save SMSAgentSoftware/7b6eb77244319c180775589fd8074edc to your computer and use it in GitHub Desktop.
Reads the most recent and next scheduled evaluation times on the local machine for ConfigMgr Compliance Baselines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################## | |
## ## | |
## Reads the most recent and next scheduled evaluation time ## | |
## for deployed Compliance Baselines from the Scheduler.log ## | |
## ## | |
############################################################## | |
#requires -RunAsAdministrator | |
# Get Baselines from WMI | |
# Excludes co-management policies | |
Try | |
{ | |
$Instances = Get-CimInstance -Namespace ROOT\ccm\dcm -ClassName SMS_DesiredConfiguration -Filter "PolicyType!=1" -OperationTimeoutSec 5 -ErrorAction Stop | Select DisplayName,IsMachineTarget,Name | |
} | |
Catch | |
{ | |
Throw "Couldn't get baseline info from WMI: $_" | |
} | |
If ($Instances.Count -eq 0) | |
{ | |
Throw "No deployed baselines found!" | |
} | |
# Datatable to hold the baselines for the WPF window | |
$DataTable = New-Object System.Data.DataTable | |
[void]$DataTable.Columns.Add("DisplayName") | |
[void]$DataTable.Columns.Add("IsMachineTarget") | |
foreach ($Instance in ($Instances | Sort DisplayName)) | |
{ | |
[void]$DataTable.Rows.Add($Instance.DisplayName,$Instance.IsMachineTarget) | |
} | |
# WPF Window for baseline selection | |
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase | |
$Window = New-Object System.Windows.Window | |
$Window.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen | |
$Window.SizeToContent = [System.Windows.SizeToContent]::WidthAndHeight | |
$window.ResizeMode = [System.Windows.ResizeMode]::NoResize | |
$Window.Title = "DOUBLE-CLICK A BASELINE TO SELECT" | |
$DataGrid = New-Object System.Windows.Controls.DataGrid | |
$DataGrid.ItemsSource = $DataTable.DefaultView | |
$DataGrid.CanUserAddRows = $False | |
$DataGrid.IsReadOnly = $true | |
$DataGrid.SelectionMode = [System.Windows.Controls.DataGridSelectionMode]::Single | |
$DataGrid.Height = "NaN" | |
$DataGrid.MaxHeight = "250" | |
$DataGrid.Width = "NaN" | |
$DataGrid.AlternatingRowBackground = "#e6ffcc" | |
$DataGrid.Add_MouseDoubleClick({ | |
$script:SelectedRow = $This.SelectedValue | |
$Window.Close() | |
}) | |
$Window.AddChild($DataGrid) | |
[void]$Window.ShowDialog() | |
If (!$SelectedRow) | |
{ | |
Throw "No baseline was selected!" | |
} | |
# If the baseline is user-targetted | |
If ($SelectedRow.row.IsMachineTarget -eq $false) | |
{ | |
# Get Logged-on user SID | |
$LogonUIRegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI" | |
#Could also use this: | |
#Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\SMS\CurrentUser -Name UserSID -ErrorAction Stop | |
$Property = "LastLoggedOnUserSID" | |
$LastLoggedOnUserSID = Get-ItemProperty -Path $LogonUIRegPath -Name $Property | Select -ExpandProperty $Property | |
$LastLoggedOnUserSIDUnderscore = $LastLoggedOnUserSID.Replace('-','_') | |
$Namespace = "ROOT\ccm\Policy\$LastLoggedOnUserSIDUnderscore\ActualConfig" | |
} | |
Else | |
{ | |
$Namespace = "ROOT\ccm\Policy\Machine\ActualConfig" | |
} | |
# Get assignment info | |
$BaselineName = $SelectedRow.Row.DisplayName | |
$Pattern = [Regex]::Escape($BaselineName) | |
$CIAssignment = Get-CimInstance -Namespace $Namespace -ClassName CCM_DCMCIAssignment | where {$_.AssignmentName -match $Pattern} | |
$AssignmentIDs = $CIAssignment | Select AssignmentID,AssignmentName | |
Write-host "Baseline: $BaselineName" -ForegroundColor Magenta | |
foreach ($AssignmentID in $AssignmentIDs) | |
{ | |
# Read the scheduler log | |
$Log = "$env:SystemRoot\CCM\Logs\Scheduler.log" | |
If ($SelectedRow.row.IsMachineTarget -eq $false) | |
{ | |
$LogEntries = Select-String -Path $Log -SimpleMatch "$LastLoggedOnUserSID/$($AssignmentID.AssignmentID)" | |
} | |
Else | |
{ | |
$LogEntries = Select-String -Path $Log -SimpleMatch "Machine/$($AssignmentID.AssignmentID)" | |
} | |
If ($LogEntries) | |
{ | |
# Get the previous evaluations date/time | |
$Evaluations = New-Object System.Collections.ArrayList | |
$EvaluationEntries = $LogEntries | where {$_ -match "SMSTrigger"} | |
Foreach ($Entry in $EvaluationEntries) | |
{ | |
$Time = $Entry.Line.Split('=')[1] | |
$Date = $Entry.Line.Split('=')[2] | |
$a = $Time.Split()[0].trimend().replace('"','') | |
$b = $Date.Split()[0].trimend().replace('"','').replace('-','/') | |
$Time = (Get-Date $a).ToLongTimeString() | |
$Date = [DateTime]"$b $Time" | |
$LocalDate = Get-Date $date -Format (Get-Culture).DateTimeFormat.RFC1123Pattern | |
[void]$Evaluations.Add($LocalDate) | |
} | |
# Get the next scheduled evaluation date/time | |
$LastEvaluation = $EvaluationEntries | Select -Last 1 | |
$date = $LastEvaluation.Line.Split()[8] | |
$time = $LastEvaluation.Line.Split()[9] | |
$ampm = $LastEvaluation.Line.Split()[10] | |
$NextEvaluation = [DateTime]"$date $time $ampm" | |
$NextEvaluationLocal = Get-Date $NextEvaluation -Format (Get-Culture).DateTimeFormat.RFC1123Pattern | |
# Return the results | |
Write-Host "Assignment: $($AssignmentID.AssignmentName)" -ForegroundColor Green | |
Write-host "Last Evaluations:" | |
foreach ($Evaluation in $Evaluations) | |
{ | |
Write-host " $Evaluation" -ForegroundColor Yellow | |
} | |
Write-host "Next Scheduled Evaluation:" | |
Write-Host " $NextEvaluationLocal" -ForegroundColor Yellow | |
} | |
Else | |
{ | |
Write-Host "No log entries found!" -ForegroundColor Red | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment