Skip to content

Instantly share code, notes, and snippets.

@SMSAgentSoftware
Last active May 1, 2020 08:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SMSAgentSoftware/7b6eb77244319c180775589fd8074edc to your computer and use it in GitHub Desktop.
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
##############################################################
## ##
## 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