Skip to content

Instantly share code, notes, and snippets.

@alx9r
Last active December 8, 2024 00:19
Show Gist options
  • Save alx9r/866202e61ebef05eb73d3f4d19b09a27 to your computer and use it in GitHub Desktop.
Save alx9r/866202e61ebef05eb73d3f4d19b09a27 to your computer and use it in GitHub Desktop.
Test for missed events when subscribed to __InstanceCreationEvent
# https://stackoverflow.com/a/79258729/1404637
param(
[ValidateSet('user','admin')]
$privileges = 'user'
)
function Invoke-Test {
param(
[int]
[ValidateRange(1,[int]::MaxValue)]
[Alias('processes')]
$n = 10,
[ValidateRange(0,1000)]
[double]$polling_interval_s = 1,
[ValidateRange(0,1000)]
[double]$start_delay = 2,
[double]
$timeout_s = 5,
[string]
$processName = 'cmd.exe',
[string[]]
$argumentList = @('/c','ver'),
[ValidateSet('user','admin')]
$privileges = 'user'
)
$sourceId = [guid]::NewGuid().guid
switch ($privileges) {
'user' {
Register-CimIndicationEvent `
-Query "SELECT *
FROM __InstanceCreationEvent
WITHIN $polling_interval_s
WHERE TargetInstance ISA 'Win32_Process'" `
-SourceIdentifier $sourceId
}
'admin' {
Register-CimIndicationEvent `
-ClassName Win32_ProcessStartTrace `
-SourceIdentifier $sourceId
}
}
Start-Sleep `
-Milliseconds (1000 *
$start_delay )
$cpu_time_s_before =
Get-Counter '\Process(WmiPrvSE)\Elapsed Time' |
% {$_.CounterSamples.CookedValue } |
Measure-Object -Sum |
% Sum
$test_duration = [System.Diagnostics.Stopwatch]::StartNew()
$processes =
@(foreach ($i in 1..$n) {
Start-Process `
-FilePath $processName `
-ArgumentList $argumentList `
-PassThru
})
$received = 0
$ids = [System.Collections.Generic.HashSet[int]]::new()
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while (-not ($timed_out = $stopwatch.Elapsed.TotalSeconds -ge $timeout_s) -and
($ids.Count -lt $n) ) {
foreach ($event in (Wait-Event `
-SourceIdentifier $sourceId `
-Timeout 1 )) {
$stopwatch.Restart()
switch ($privileges) {
'user' {
$instanceName = $event.SourceEventArgs.NewEvent.TargetInstance.Name
$instanceProcessId = $event.SourceEventArgs.NewEvent.TargetInstance.ProcessId
}
'admin' {
$instanceName = $event.SourceEventArgs.NewEvent.ProcessName
$instanceProcessId = $event.SourceEventArgs.NewEvent.ProcessID
}
}
$event | Remove-Event
if ($instanceName -ne $processName) {
continue
}
$received += 1
$ids.Add($instanceProcessID) | Out-Null
Write-Verbose "unique: $($ids.Count), received: $received, this ID $($instanceProcessID)"
}
}
$test_duration.Stop()
$cpu_time_s_after =
Get-Counter '\Process(WmiPrvSE)\Elapsed Time' |
% {$_.CounterSamples.CookedValue } |
Measure-Object -Sum |
% Sum
Get-EventSubscriber `
-SourceIdentifier $sourceId |
Unregister-Event
Remove-Event `
-SourceIdentifier $sourceId `
-ErrorAction SilentlyContinue
$processes | Wait-Process
[pscustomobject]@{
Count = $ids.Count
TimedOut = $timed_out
cpu_time_s = $cpu_time_s_after - $cpu_time_s_before
test_duration = $test_duration.Elapsed
}
}
$expected_processes = 10
foreach ($polling_interval_s in 0.001,0.003,0.005,0.01,0.03,0.05,0.1,0.3,0.5) {
foreach ($trial in 1..10) {
$result =
Invoke-Test `
-processes $expected_processes `
-polling_interval_s $polling_interval_s `
-start_delay ($start_delay_s = 2) `
-timeout_s ($timeout_s = 3) `
-privileges $privileges
[pscustomobject]@{
polling_interval_ms = [int]($polling_interval_s*1000)
trial = $trial
expected = $expected_processes
actual = ($actual = $result | % Count)
lost = ($lost = $expected_processes - $actual)
result = if ($lost) { "❌" } else {"✅"}
cpu_time_s = ($cpu_time_s = $result.cpu_time_s)
test_duration_s = ($test_duration_s = $result.test_duration.TotalSeconds)
apparent_processor_load = "$([int]($cpu_time_s * 100 / $test_duration_s / [System.Environment]::ProcessorCount))%"
timed_out = $result.TimedOut
start_delay_s = $start_delay_s
timeout_s = $timeout_s
}
}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment