diff --git a/docs/ocsentinel-deployment.md b/docs/ocsentinel-deployment.md
index fcc03b2..92c6ca2 100644
--- a/docs/ocsentinel-deployment.md
+++ b/docs/ocsentinel-deployment.md
@@ -39,12 +39,21 @@ The installer creates two Windows Scheduled Tasks running as `SYSTEM`:
`04:00` and `06:59`, derived from its Windows `MachineGuid`. This distributes
a fleet rollout instead of sending all reports at the same time.
- `OCSentinel Burst Check`: runs every five minutes. It performs no scan unless
- the NinjaOne device custom field `ocsentinelburst` is enabled.
+ the NinjaOne device custom field `ocsentinelburst` is enabled. Once enabled,
+ it scans for two hours and then disables itself automatically.
Create `ocsentinelburst` as a device-level `Checkbox` custom field and allow
-automation read access. Set it to `true` for a device to begin the five-minute
-burst scans; clear it to stop them. The normal daily scan continues regardless
-of the checkbox.
+automation read and write access. Set it to `true` for a device to begin the
+five-minute burst scans; clear it to stop them early. The normal daily scan
+continues regardless of the checkbox.
+
+Create these accompanying device custom fields and allow automation write
+access:
+
+| Field name | Type | Purpose |
+| --- | --- | --- |
+| `ocsentinelburstuntilutc` | Date/Time | UTC time at which the active burst ends |
+| `ocsentinelburststatus` | Text | `idle`, `active until ...`, or `completed` |
## Upload Reliability And Client Health
diff --git a/installer/runtime-run-ocsentinel-scheduled.ps1 b/installer/runtime-run-ocsentinel-scheduled.ps1
index f48aecb..1449087 100644
--- a/installer/runtime-run-ocsentinel-scheduled.ps1
+++ b/installer/runtime-run-ocsentinel-scheduled.ps1
@@ -1,7 +1,9 @@
[CmdletBinding()]
param(
[ValidateSet("daily", "burst")]
- [string]$Kind = "daily"
+ [string]$Kind = "daily",
+ [ValidateRange(15, 480)]
+ [int]$BurstDurationMinutes = 120
)
$ErrorActionPreference = "Stop"
@@ -25,9 +27,69 @@ function Get-NinjaBurstEnabled {
return $false
}
-if ($Kind -eq "burst" -and -not (Get-NinjaBurstEnabled)) {
- Write-Host "OfficeCom Sentinel burst check: disabled."
- exit 0
+function Get-NinjaValue {
+ param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Type)
+
+ try {
+ if (Get-Command -Name "Get-NinjaProperty" -ErrorAction SilentlyContinue) {
+ return Get-NinjaProperty -Name $Name -Type $Type
+ }
+ if (Get-Command -Name "Ninja-Property-Get" -ErrorAction SilentlyContinue) {
+ return Ninja-Property-Get -Name $Name
+ }
+ }
+ catch {
+ Write-Warning "Could not read Ninja field '$Name': $($_.Exception.Message)"
+ }
+ return $null
+}
+
+function Set-NinjaValue {
+ param([Parameter(Mandatory)][string]$Name, [AllowEmptyString()][string]$Value, [Parameter(Mandatory)][string]$Type)
+
+ try {
+ if (Get-Command -Name "Set-NinjaProperty" -ErrorAction SilentlyContinue) {
+ Set-NinjaProperty -Name $Name -Value $Value -Type $Type -Force | Out-Null
+ return $true
+ }
+ if (Get-Command -Name "Ninja-Property-Set" -ErrorAction SilentlyContinue) {
+ Ninja-Property-Set -Name $Name -Value $Value | Out-Null
+ return $true
+ }
+ }
+ catch {
+ Write-Warning "Could not update Ninja field '$Name': $($_.Exception.Message)"
+ }
+ return $false
+}
+
+if ($Kind -eq "burst") {
+ if (-not (Get-NinjaBurstEnabled)) {
+ Set-NinjaValue -Name "ocsentinelburststatus" -Value "idle" -Type "Text" | Out-Null
+ Write-Host "OfficeCom Sentinel burst check: disabled."
+ exit 0
+ }
+
+ $now = [DateTimeOffset]::UtcNow
+ $untilValue = Get-NinjaValue -Name "ocsentinelburstuntilutc" -Type "DateTime"
+ $until = $null
+ if (-not [string]::IsNullOrWhiteSpace([string]$untilValue)) {
+ try { $until = [DateTimeOffset]$untilValue } catch { Write-Warning "Burst end time is invalid and will be restarted." }
+ }
+
+ if ($null -eq $until) {
+ $until = $now.AddMinutes($BurstDurationMinutes)
+ Set-NinjaValue -Name "ocsentinelburstuntilutc" -Value $until.ToString("o") -Type "DateTime" | Out-Null
+ Write-Host "OfficeCom Sentinel burst window started until $($until.ToString('u'))."
+ }
+ elseif ($until -le $now) {
+ Set-NinjaValue -Name "ocsentinelburst" -Value "false" -Type "Checkbox" | Out-Null
+ Set-NinjaValue -Name "ocsentinelburststatus" -Value "completed" -Type "Text" | Out-Null
+ Write-Host "OfficeCom Sentinel burst window completed and was disabled."
+ exit 0
+ }
+
+ Set-NinjaValue -Name "ocsentinelburststatus" -Value "active until $($until.ToUniversalTime().ToString('o'))" -Type "Text" | Out-Null
}
$createdNew = $false
@@ -39,7 +101,11 @@ try {
}
Write-Host "OfficeCom Sentinel scheduled $Kind scan started."
- & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitorScript -Mode status -UploadMode required -SecretPath $secretPath -SuppressTriggerExit
+ $monitorArgs = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $monitorScript, "-Mode", "status", "-UploadMode", "required", "-SecretPath", $secretPath, "-SuppressTriggerExit")
+ if ($Kind -eq "burst") {
+ $monitorArgs += @("-LookbackDays", "1", "-TopCount", "25")
+ }
+ & powershell.exe @monitorArgs
exit $LASTEXITCODE
}
finally {
diff --git a/scripts/run-ocsentinel-scheduled.ps1 b/scripts/run-ocsentinel-scheduled.ps1
index f48aecb..1449087 100644
--- a/scripts/run-ocsentinel-scheduled.ps1
+++ b/scripts/run-ocsentinel-scheduled.ps1
@@ -1,7 +1,9 @@
[CmdletBinding()]
param(
[ValidateSet("daily", "burst")]
- [string]$Kind = "daily"
+ [string]$Kind = "daily",
+ [ValidateRange(15, 480)]
+ [int]$BurstDurationMinutes = 120
)
$ErrorActionPreference = "Stop"
@@ -25,9 +27,69 @@ function Get-NinjaBurstEnabled {
return $false
}
-if ($Kind -eq "burst" -and -not (Get-NinjaBurstEnabled)) {
- Write-Host "OfficeCom Sentinel burst check: disabled."
- exit 0
+function Get-NinjaValue {
+ param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Type)
+
+ try {
+ if (Get-Command -Name "Get-NinjaProperty" -ErrorAction SilentlyContinue) {
+ return Get-NinjaProperty -Name $Name -Type $Type
+ }
+ if (Get-Command -Name "Ninja-Property-Get" -ErrorAction SilentlyContinue) {
+ return Ninja-Property-Get -Name $Name
+ }
+ }
+ catch {
+ Write-Warning "Could not read Ninja field '$Name': $($_.Exception.Message)"
+ }
+ return $null
+}
+
+function Set-NinjaValue {
+ param([Parameter(Mandatory)][string]$Name, [AllowEmptyString()][string]$Value, [Parameter(Mandatory)][string]$Type)
+
+ try {
+ if (Get-Command -Name "Set-NinjaProperty" -ErrorAction SilentlyContinue) {
+ Set-NinjaProperty -Name $Name -Value $Value -Type $Type -Force | Out-Null
+ return $true
+ }
+ if (Get-Command -Name "Ninja-Property-Set" -ErrorAction SilentlyContinue) {
+ Ninja-Property-Set -Name $Name -Value $Value | Out-Null
+ return $true
+ }
+ }
+ catch {
+ Write-Warning "Could not update Ninja field '$Name': $($_.Exception.Message)"
+ }
+ return $false
+}
+
+if ($Kind -eq "burst") {
+ if (-not (Get-NinjaBurstEnabled)) {
+ Set-NinjaValue -Name "ocsentinelburststatus" -Value "idle" -Type "Text" | Out-Null
+ Write-Host "OfficeCom Sentinel burst check: disabled."
+ exit 0
+ }
+
+ $now = [DateTimeOffset]::UtcNow
+ $untilValue = Get-NinjaValue -Name "ocsentinelburstuntilutc" -Type "DateTime"
+ $until = $null
+ if (-not [string]::IsNullOrWhiteSpace([string]$untilValue)) {
+ try { $until = [DateTimeOffset]$untilValue } catch { Write-Warning "Burst end time is invalid and will be restarted." }
+ }
+
+ if ($null -eq $until) {
+ $until = $now.AddMinutes($BurstDurationMinutes)
+ Set-NinjaValue -Name "ocsentinelburstuntilutc" -Value $until.ToString("o") -Type "DateTime" | Out-Null
+ Write-Host "OfficeCom Sentinel burst window started until $($until.ToString('u'))."
+ }
+ elseif ($until -le $now) {
+ Set-NinjaValue -Name "ocsentinelburst" -Value "false" -Type "Checkbox" | Out-Null
+ Set-NinjaValue -Name "ocsentinelburststatus" -Value "completed" -Type "Text" | Out-Null
+ Write-Host "OfficeCom Sentinel burst window completed and was disabled."
+ exit 0
+ }
+
+ Set-NinjaValue -Name "ocsentinelburststatus" -Value "active until $($until.ToUniversalTime().ToString('o'))" -Type "Text" | Out-Null
}
$createdNew = $false
@@ -39,7 +101,11 @@ try {
}
Write-Host "OfficeCom Sentinel scheduled $Kind scan started."
- & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitorScript -Mode status -UploadMode required -SecretPath $secretPath -SuppressTriggerExit
+ $monitorArgs = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $monitorScript, "-Mode", "status", "-UploadMode", "required", "-SecretPath", $secretPath, "-SuppressTriggerExit")
+ if ($Kind -eq "burst") {
+ $monitorArgs += @("-LookbackDays", "1", "-TopCount", "25")
+ }
+ & powershell.exe @monitorArgs
exit $LASTEXITCODE
}
finally {
diff --git a/src/OCSentinelCli/OCSentinelCli.csproj b/src/OCSentinelCli/OCSentinelCli.csproj
index 0ce2e82..5cbf053 100644
--- a/src/OCSentinelCli/OCSentinelCli.csproj
+++ b/src/OCSentinelCli/OCSentinelCli.csproj
@@ -9,10 +9,10 @@
OCSentinelCli
OfficeCom Sentinel
OfficeCom
- 1.3.3
- 1.3.3.0
- 1.3.3.0
- 1.3.3
+ 1.3.4
+ 1.3.4.0
+ 1.3.4.0
+ 1.3.4