Merge pull request #15 from igor04091968/devin/1777897921-print-docname-ansible-innosetup

fix(print): исправление имени документа «Печать документа» + интеграция email collector в деплой
This commit is contained in:
IgorRachkov
2026-05-07 07:34:42 +03:00
committed by GitHub
19 changed files with 375 additions and 67 deletions
+1
View File
@@ -78,6 +78,7 @@
- ActivityWatch.Windows.Common.psm1
- browser-domains-native-collector.ps1
- dlp-endpoint-signals-collector.ps1
- email-outbound-collector.ps1
- file-operations-collector.ps1
- worktime-session-collector.ps1
- migrate-awatch-rus-paths.ps1
+2
View File
@@ -28,6 +28,8 @@ aw_windows_state_root: "C:\\ProgramData\\AWatch-rus"
aw_windows_afk_enabled: true
aw_windows_window_enabled: true
aw_windows_file_ops_enabled: true
aw_windows_email_collector_enabled: true
aw_windows_email_collector_mode: "both"
aw_windows_local_agent_logs_enabled: false
aw_windows_incident_capture_enabled: true
aw_windows_incident_screenshot_enabled: true
@@ -32,6 +32,7 @@ b497400a1ba57cddf28dc8e217115dc85eccb67150cbdbb6a81abd804ed20109 install-kit-aw
973db51854fc744539a7b75e13c6749e822a08a79f47447485611f07e8f902a8 install-kit-awindows-20260427-211240/windows/deploy-ensemble.ps1
0d66dcb551889e6b7bc21b29d53b77e46f41d61dd2e4e0d9913dbf0f8bd5eb18 install-kit-awindows-20260427-211240/windows/deploy-single-user.ps1
8857f3e17f3f3ed6f211ce7f0a0c46c586a2548541078401ee3befaa20924b3d install-kit-awindows-20260427-211240/windows/dlp-endpoint-signals-collector.ps1
7362e1aecb56d8863b8b2542f262f28827febf9b25a2a14b382750dc6368664f install-kit-awindows-20260427-211240/windows/email-outbound-collector.ps1
aef0032edd9b1e0c54f7b575664ed511dfc6cb53364e7496cbc95e137678e11a install-kit-awindows-20260427-211240/windows/dlp-policy.example.json
f03886caf56c6838e8a163d6b48d1f229e83a5682aeeb447c3a65f13d62dbca4 install-kit-awindows-20260427-211240/windows/hardening-recovery.ps1
71911cd53ad0abd8bf83994f8a79bbbfe2c0eaf4f4c5f6c2d636dd7786191c2f install-kit-awindows-20260427-211240/windows/migrate-awatch-rus-paths.ps1
@@ -77,6 +77,7 @@
- ActivityWatch.Windows.Common.psm1
- browser-domains-native-collector.ps1
- dlp-endpoint-signals-collector.ps1
- email-outbound-collector.ps1
- worktime-session-collector.ps1
- migrate-awatch-rus-paths.ps1
- deploy-domain-users.ps1
@@ -12,6 +12,7 @@
"logsRoot": "C:\\ProgramData\\AWatch-rus\\logs",
"collectorScript": "C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1",
"endpointCollectorScript": "C:\\ProgramData\\AWatch-rus\\dlp-endpoint-signals-collector.ps1",
"emailCollectorScript": "C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1",
"rulesPath": "C:\\ProgramData\\AWatch-rus\\web-category-rules.json",
"policyPath": "C:\\ProgramData\\AWatch-rus\\dlp-policy.json",
"launchScript": "C:\\ProgramData\\AWatch-rus\\launch-watchers.ps1",
@@ -12,6 +12,7 @@
"logsRoot": "C:\\ProgramData\\AWatch-rus\\logs",
"collectorScript": "C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1",
"endpointCollectorScript": "C:\\ProgramData\\AWatch-rus\\dlp-endpoint-signals-collector.ps1",
"emailCollectorScript": "C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1",
"rulesPath": "C:\\ProgramData\\AWatch-rus\\web-category-rules.json",
"policyPath": "C:\\ProgramData\\AWatch-rus\\dlp-policy.json",
"launchScript": "C:\\ProgramData\\AWatch-rus\\launch-watchers.ps1",
@@ -12,6 +12,7 @@
"logsRoot": "C:\\ProgramData\\AWatch-rus\\logs",
"collectorScript": "C:\\ProgramData\\AWatch-rus\\browser-domains-native-collector.ps1",
"endpointCollectorScript": "C:\\ProgramData\\AWatch-rus\\dlp-endpoint-signals-collector.ps1",
"emailCollectorScript": "C:\\ProgramData\\AWatch-rus\\email-outbound-collector.ps1",
"rulesPath": "C:\\ProgramData\\AWatch-rus\\web-category-rules.json",
"policyPath": "C:\\ProgramData\\AWatch-rus\\dlp-policy.json",
"launchScript": "C:\\ProgramData\\AWatch-rus\\launch-watchers.ps1",
@@ -20,6 +20,17 @@ function New-ActivityWatchDirectory {
}
}
function Enable-ActivityWatchPrintTelemetry {
$policyPath = 'HKLM:\Software\Policies\Microsoft\Windows NT\Printers'
if (-not (Test-Path -LiteralPath $policyPath)) {
New-Item -Path $policyPath -Force | Out-Null
}
New-ItemProperty -Path $policyPath -Name 'ShowJobTitleInEventLogs' -Value 1 -PropertyType DWord -Force | Out-Null
& wevtutil.exe sl 'Microsoft-Windows-PrintService/Operational' /e:true | Out-Null
}
function Get-ActivityWatchPackageUrl {
param(
[string]$Version = 'v0.13.2'
@@ -49,7 +60,9 @@ function Get-ActivityWatchArchive {
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$archivePath = Join-Path $WorkingRoot ("activitywatch-{0}.zip" -f $Version.TrimStart('v'))
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$suffix = ([guid]::NewGuid().Guid.Substring(0, 8))
$archivePath = Join-Path $WorkingRoot ("activitywatch-{0}-{1}-{2}.zip" -f $Version.TrimStart('v'), $stamp, $suffix)
Invoke-WebRequest -Uri $PackageUrl -OutFile $archivePath
return $archivePath
}
@@ -85,6 +98,16 @@ function Install-ActivityWatchPackage {
New-ActivityWatchDirectory -Path $WorkingRoot
New-ActivityWatchDirectory -Path $BackupRoot
# Ensure nothing is holding locks inside InstallRoot during upgrade.
foreach ($procName in @('aw-watcher-afk', 'aw-watcher-window', 'aw-server', 'aw-qt')) {
try {
Get-Process -Name $procName -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
}
catch {
}
}
Start-Sleep -Seconds 2
$extractRoot = Join-Path $WorkingRoot ('extract-' + [guid]::NewGuid().Guid)
if (Test-Path -LiteralPath $extractRoot) {
Remove-Item -LiteralPath $extractRoot -Recurse -Force
@@ -243,7 +266,10 @@ function Copy-ActivityWatchCollectorAssets {
[Parameter(Mandatory = $true)]
[string]$EndpointCollectorScriptSource,
[Parameter(Mandatory = $true)]
[string]$FileCollectorScriptSource,
[Parameter(Mandatory = $true)]
[string]$SessionCollectorScriptSource,
[string]$EmailCollectorScriptSource,
[Parameter(Mandatory = $true)]
[string]$ExampleRulesSource,
[Parameter(Mandatory = $true)]
@@ -258,7 +284,9 @@ function Copy-ActivityWatchCollectorAssets {
$collectorTarget = Join-Path $StateRoot 'browser-domains-native-collector.ps1'
$endpointCollectorTarget = Join-Path $StateRoot 'dlp-endpoint-signals-collector.ps1'
$fileCollectorTarget = Join-Path $StateRoot 'file-operations-collector.ps1'
$sessionCollectorTarget = Join-Path $StateRoot 'worktime-session-collector.ps1'
$emailCollectorTarget = Join-Path $StateRoot 'email-outbound-collector.ps1'
$exampleRulesTarget = Join-Path $StateRoot 'web-category-rules.example.json'
$rulesTarget = Join-Path $StateRoot 'web-category-rules.json'
$examplePolicyTarget = Join-Path $StateRoot 'dlp-policy.example.json'
@@ -266,7 +294,11 @@ function Copy-ActivityWatchCollectorAssets {
Copy-Item -LiteralPath $CollectorScriptSource -Destination $collectorTarget -Force
Copy-Item -LiteralPath $EndpointCollectorScriptSource -Destination $endpointCollectorTarget -Force
Copy-Item -LiteralPath $FileCollectorScriptSource -Destination $fileCollectorTarget -Force
Copy-Item -LiteralPath $SessionCollectorScriptSource -Destination $sessionCollectorTarget -Force
if ($EmailCollectorScriptSource -and (Test-Path -LiteralPath $EmailCollectorScriptSource)) {
Copy-Item -LiteralPath $EmailCollectorScriptSource -Destination $emailCollectorTarget -Force
}
Copy-Item -LiteralPath $ExampleRulesSource -Destination $exampleRulesTarget -Force
Copy-Item -LiteralPath $ExamplePolicySource -Destination $examplePolicyTarget -Force
@@ -286,7 +318,9 @@ function Copy-ActivityWatchCollectorAssets {
return [pscustomobject]@{
CollectorScript = $collectorTarget
EndpointCollectorScript = $endpointCollectorTarget
FileCollectorScript = $fileCollectorTarget
SessionCollectorScript = $sessionCollectorTarget
EmailCollectorScript = $emailCollectorTarget
ExampleRules = $exampleRulesTarget
ActiveRules = $rulesTarget
ExamplePolicy = $examplePolicyTarget
@@ -313,7 +347,10 @@ function New-ActivityWatchDeploymentConfig {
[Parameter(Mandatory = $true)]
[string]$EndpointCollectorScript,
[Parameter(Mandatory = $true)]
[string]$FileCollectorScript,
[Parameter(Mandatory = $true)]
[string]$SessionCollectorScript,
[string]$EmailCollectorScript,
[Parameter(Mandatory = $true)]
[string]$RulesPath,
[Parameter(Mandatory = $true)]
@@ -326,6 +363,7 @@ function New-ActivityWatchDeploymentConfig {
[int]$RecoveryIntervalSeconds,
[bool]$AfkEnabled = $true,
[bool]$WindowEnabled = $true,
[bool]$FileOpsEnabled = $true,
[bool]$LocalAgentLogsEnabled = $true,
[bool]$IncidentCaptureEnabled = $true,
[bool]$IncidentScreenshotEnabled = $true,
@@ -356,6 +394,8 @@ function New-ActivityWatchDeploymentConfig {
logsRoot = $LogsRoot
collectorScript = $CollectorScript
endpointCollectorScript = $EndpointCollectorScript
emailCollectorScript = $EmailCollectorScript
fileCollectorScript = $FileCollectorScript
sessionCollectorScript = $SessionCollectorScript
rulesPath = $RulesPath
policyPath = $PolicyPath
@@ -369,6 +409,8 @@ function New-ActivityWatchDeploymentConfig {
collectors = [pscustomobject]@{
afkEnabled = $AfkEnabled
windowEnabled = $WindowEnabled
fileOpsEnabled = $FileOpsEnabled
emailEnabled = ($null -ne $EmailCollectorScript -and $EmailCollectorScript -ne '')
}
logging = [pscustomobject]@{
localAgentLogsEnabled = $LocalAgentLogsEnabled
@@ -443,6 +485,10 @@ param(
Set-StrictMode -Version Latest
`$ErrorActionPreference = 'Stop'
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
Add-Type -AssemblyName System.Net.Http
`$script:MaxCollectorPowerShellProcesses = 24
function Get-DeploymentConfig {
param([string]`$Path)
return Get-Content -LiteralPath `$Path -Raw | ConvertFrom-Json
@@ -474,14 +520,67 @@ function Test-CollectorRunning {
return [bool](`$processes | Select-Object -First 1)
}
function Get-CollectorPowerShellProcessCount {
`$processes = Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
Where-Object {
(`$_.Name -ieq 'powershell.exe' -or `$_.Name -ieq 'pwsh.exe') -and
`$_.CommandLine -match 'AWatch-rus' -and
`$_.CommandLine -match '\.ps1'
}
return @(`$processes).Count
}
function New-LaunchLock {
param([string]`$StateRoot, [int]`$SessionId)
if (-not (Test-Path -LiteralPath `$StateRoot)) {
New-Item -Path `$StateRoot -ItemType Directory -Force | Out-Null
}
`$lockPath = Join-Path `$StateRoot ("launch-watchers-session-{0}.lock" -f `$SessionId)
if (Test-Path -LiteralPath `$lockPath) {
try {
`$lockData = Get-Content -LiteralPath `$lockPath -Raw | ConvertFrom-Json
`$existingPid = [int]`$lockData.pid
if (`$existingPid -gt 0 -and (Get-Process -Id `$existingPid -ErrorAction SilentlyContinue)) {
return `$null
}
}
catch {
}
}
`$payload = @{
pid = `$PID
sessionId = `$SessionId
createdAt = (Get-Date).ToUniversalTime().ToString('o')
} | ConvertTo-Json -Compress
Set-Content -LiteralPath `$lockPath -Value `$payload -Encoding UTF8
return `$lockPath
}
function Invoke-AwJsonPost {
param(
[Parameter(Mandatory = `$true)][string]`$Uri,
[Parameter(Mandatory = `$true)][string]`$Json
)
`$bytes = [Text.Encoding]::UTF8.GetBytes(`$Json)
Invoke-RestMethod -Method Post -Uri `$Uri -ContentType 'application/json; charset=utf-8' -Body `$bytes | Out-Null
`$httpClient = New-Object System.Net.Http.HttpClient
try {
`$content = New-Object System.Net.Http.StringContent(`$Json, [System.Text.Encoding]::UTF8, 'application/json')
`$response = `$httpClient.PostAsync(`$Uri, `$content).Result
if (-not `$response.IsSuccessStatusCode) {
return `$false
}
return `$true
}
catch {
return `$false
}
finally {
`$httpClient.Dispose()
}
}
function Ensure-Bucket {
@@ -510,7 +609,9 @@ function Ensure-Bucket {
} | ConvertTo-Json -Compress
try {
Invoke-AwJsonPost -Uri "`$(`$script:ApiBase)/buckets/`$BucketId" -Json `$body
if (-not (Invoke-AwJsonPost -Uri "`$(`$script:ApiBase)/buckets/`$BucketId" -Json `$body)) {
return
}
}
catch {
try {
@@ -614,6 +715,10 @@ function Start-CollectorScriptIfNeeded {
[int]`$SessionId
)
if ([string]::IsNullOrWhiteSpace(`$ScriptPath)) {
return
}
if (-not (Test-Path -LiteralPath `$ScriptPath)) {
return
}
@@ -622,6 +727,10 @@ function Start-CollectorScriptIfNeeded {
return
}
if ((Get-CollectorPowerShellProcessCount) -ge `$script:MaxCollectorPowerShellProcesses) {
return
}
Start-Process -FilePath `$PowerShellExe -ArgumentList @(
'-NoProfile',
'-WindowStyle', 'Hidden',
@@ -634,43 +743,65 @@ function Start-CollectorScriptIfNeeded {
`$config = Get-DeploymentConfig -Path `$ConfigPath
`$sessionId = (Get-Process -Id `$PID).SessionId
`$installRoot = [string]`$config.paths.installRoot
`$stateRoot = [string]`$config.paths.stateRoot
`$script:ApiBase = '{0}://{1}:{2}/api/0' -f [string]`$config.server.scheme, [string]`$config.server.host, [string]`$config.server.port
`$script:Hostname = `$env:COMPUTERNAME
`$script:KnownBuckets = @{}
`$collectorScript = [string]`$config.paths.collectorScript
`$endpointCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { [string]`$config.paths.endpointCollectorScript } else { '' }
`$sessionCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'sessionCollectorScript') { [string]`$config.paths.sessionCollectorScript } else { '' }
`$endpointCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { [string]`$config.paths.endpointCollectorScript } else { Join-Path `$stateRoot 'dlp-endpoint-signals-collector.ps1' }
`$fileCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'fileCollectorScript') { [string]`$config.paths.fileCollectorScript } else { Join-Path `$stateRoot 'file-operations-collector.ps1' }
`$sessionCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'sessionCollectorScript') { [string]`$config.paths.sessionCollectorScript } else { Join-Path `$stateRoot 'worktime-session-collector.ps1' }
`$afkExe = Join-Path `$installRoot 'aw-watcher-afk\aw-watcher-afk.exe'
`$windowExe = Join-Path `$installRoot 'aw-watcher-window\aw-watcher-window.exe'
`$serverArgs = @('--host', [string]`$config.server.host, '--port', [string]`$config.server.port)
`$powershellExe = Join-Path `$env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe'
`$afkEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'afkEnabled') { [bool]`$config.collectors.afkEnabled } else { `$true }
`$windowEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'windowEnabled') { [bool]`$config.collectors.windowEnabled } else { `$true }
if (`$afkEnabled -and -not (Test-Path -LiteralPath `$afkExe)) {
throw "Не найден aw-watcher-afk.exe: `$afkExe"
}
if (`$windowEnabled -and -not (Test-Path -LiteralPath `$windowExe)) {
throw "Не найден aw-watcher-window.exe: `$windowExe"
}
if (`$afkEnabled -and -not (Test-ProcessInSession -Name 'aw-watcher-afk' -SessionId `$sessionId)) {
Start-Process -FilePath `$afkExe -ArgumentList `$serverArgs -WindowStyle Hidden
}
if (`$windowEnabled -and -not (Test-ProcessInSession -Name 'aw-watcher-window' -SessionId `$sessionId)) {
Start-Process -FilePath `$windowExe -ArgumentList `$serverArgs -WindowStyle Hidden
`$fileOpsEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'fileOpsEnabled') { [bool]`$config.collectors.fileOpsEnabled } else { `$true }
`$emailEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'emailEnabled') { [bool]`$config.collectors.emailEnabled } else { `$false }
`$emailCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'emailCollectorScript') { [string]`$config.paths.emailCollectorScript } else { Join-Path `$stateRoot 'email-outbound-collector.ps1' }
`$launchLockPath = New-LaunchLock -StateRoot `$stateRoot -SessionId `$sessionId
if (-not `$launchLockPath) {
return
}
try {
Send-LogonMarkerIfNeeded -Config `$config -SessionId `$sessionId
if (`$afkEnabled -and -not (Test-Path -LiteralPath `$afkExe)) {
throw "Не найден aw-watcher-afk.exe: `$afkExe"
}
if (`$windowEnabled -and -not (Test-Path -LiteralPath `$windowExe)) {
throw "Не найден aw-watcher-window.exe: `$windowExe"
}
if (`$afkEnabled -and -not (Test-ProcessInSession -Name 'aw-watcher-afk' -SessionId `$sessionId)) {
Start-Process -FilePath `$afkExe -ArgumentList `$serverArgs -WindowStyle Hidden
}
if (`$windowEnabled -and -not (Test-ProcessInSession -Name 'aw-watcher-window' -SessionId `$sessionId)) {
Start-Process -FilePath `$windowExe -ArgumentList `$serverArgs -WindowStyle Hidden
}
try {
Send-LogonMarkerIfNeeded -Config `$config -SessionId `$sessionId
}
catch {
}
Start-CollectorScriptIfNeeded -ScriptPath `$collectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
Start-CollectorScriptIfNeeded -ScriptPath `$endpointCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
if (`$fileOpsEnabled) {
Start-CollectorScriptIfNeeded -ScriptPath `$fileCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
}
Start-CollectorScriptIfNeeded -ScriptPath `$sessionCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
if (`$emailEnabled -and (Test-Path -LiteralPath `$emailCollectorScript)) {
Start-CollectorScriptIfNeeded -ScriptPath `$emailCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
}
}
catch {
finally {
if (`$launchLockPath -and (Test-Path -LiteralPath `$launchLockPath)) {
Remove-Item -LiteralPath `$launchLockPath -Force -ErrorAction SilentlyContinue
}
}
Start-CollectorScriptIfNeeded -ScriptPath `$collectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
Start-CollectorScriptIfNeeded -ScriptPath `$endpointCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
Start-CollectorScriptIfNeeded -ScriptPath `$sessionCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
"@
Set-Content -LiteralPath $Path -Value $content -Encoding UTF8
@@ -749,23 +880,84 @@ function Get-RecoveryTaskNames {
return @(`$taskNames)
}
while (`$true) {
`$sleepSeconds = 180
try {
`$configPaths = Get-RecoveryConfigPaths -PrimaryConfigPath `$ConfigPath
foreach (`$taskName in Get-RecoveryTaskNames -ConfigPaths `$configPaths) {
Start-ScheduledTask -TaskName `$taskName -ErrorAction SilentlyContinue
}
function New-RecoveryLock {
param([string]`$PrimaryConfigPath)
`$config = Get-DeploymentConfig -Path `$ConfigPath
if (`$config -and `$config.recovery -and `$config.recovery.intervalSeconds) {
`$sleepSeconds = [Math]::Max([int]`$config.recovery.intervalSeconds, 30)
`$stateRoot = if (`$PrimaryConfigPath) { Split-Path -Path `$PrimaryConfigPath -Parent } else { Join-Path `$env:ProgramData 'AWatch-rus' }
if (-not (Test-Path -LiteralPath `$stateRoot)) {
New-Item -Path `$stateRoot -ItemType Directory -Force | Out-Null
}
`$lockPath = Join-Path `$stateRoot 'recovery-loop.lock'
if (Test-Path -LiteralPath `$lockPath) {
try {
`$lockData = Get-Content -LiteralPath `$lockPath -Raw | ConvertFrom-Json
`$existingPid = [int]`$lockData.pid
if (`$existingPid -gt 0 -and (Get-Process -Id `$existingPid -ErrorAction SilentlyContinue)) {
return `$null
}
}
catch {
}
}
`$payload = @{
pid = `$PID
createdAt = (Get-Date).ToUniversalTime().ToString('o')
} | ConvertTo-Json -Compress
Set-Content -LiteralPath `$lockPath -Value `$payload -Encoding UTF8
return `$lockPath
}
function Start-TaskIfNotRunning {
param([string]`$TaskName)
if ([string]::IsNullOrWhiteSpace(`$TaskName)) {
return
}
try {
`$task = Get-ScheduledTask -TaskName `$TaskName -ErrorAction SilentlyContinue
if (-not `$task) {
return
}
if ([string]`$task.State -eq 'Running') {
return
}
Start-ScheduledTask -TaskName `$TaskName -ErrorAction SilentlyContinue
}
catch {
}
}
Start-Sleep -Seconds `$sleepSeconds
`$recoveryLockPath = New-RecoveryLock -PrimaryConfigPath `$ConfigPath
if (-not `$recoveryLockPath) {
return
}
try {
while (`$true) {
`$sleepSeconds = 180
try {
`$configPaths = Get-RecoveryConfigPaths -PrimaryConfigPath `$ConfigPath
foreach (`$taskName in Get-RecoveryTaskNames -ConfigPaths `$configPaths) {
Start-TaskIfNotRunning -TaskName `$taskName
}
`$config = Get-DeploymentConfig -Path `$ConfigPath
if (`$config -and `$config.recovery -and `$config.recovery.intervalSeconds) {
`$sleepSeconds = [Math]::Max([int]`$config.recovery.intervalSeconds, 30)
}
}
catch {
}
Start-Sleep -Seconds `$sleepSeconds
}
}
finally {
if (`$recoveryLockPath -and (Test-Path -LiteralPath `$recoveryLockPath)) {
Remove-Item -LiteralPath `$recoveryLockPath -Force -ErrorAction SilentlyContinue
}
}
"@
@@ -891,6 +1083,37 @@ function Get-ActivityWatchScheduledTaskByCommand {
return $null
}
function Remove-StaleActivityWatchUserTasks {
param(
[Parameter(Mandatory = $true)]
[pscustomobject[]]$TaskDefinitions,
[Parameter(Mandatory = $true)]
[string]$LaunchScriptPath
)
$launcherPath = Get-ActivityWatchHiddenLauncherPath -ScriptPath $LaunchScriptPath
$desiredTaskNames = @($TaskDefinitions | ForEach-Object { [string]$_.LaunchTaskName })
foreach ($candidate in @(Get-ScheduledTask | Where-Object { $_.TaskName -like 'ActivityWatch Launch*' })) {
$taskName = [string]$candidate.TaskName
if ($desiredTaskNames -contains $taskName) {
continue
}
$usesCurrentLauncher = $false
foreach ($action in @($candidate.Actions)) {
if ([string]$action.Arguments -like "*$launcherPath*") {
$usesCurrentLauncher = $true
break
}
}
if ($usesCurrentLauncher) {
Remove-ActivityWatchScheduledTask -TaskName $taskName
}
}
}
function Register-ActivityWatchUserTasks {
param(
[Parameter(Mandatory = $true)]
@@ -904,6 +1127,7 @@ function Register-ActivityWatchUserTasks {
$wscriptExe = Join-Path $env:SystemRoot 'System32\wscript.exe'
$launcherPath = Get-ActivityWatchHiddenLauncherPath -ScriptPath $LaunchScriptPath
Write-ActivityWatchHiddenPowerShellWrapper -Path $launcherPath -ScriptPath $LaunchScriptPath -ConfigPath $ConfigPath
Remove-StaleActivityWatchUserTasks -TaskDefinitions $TaskDefinitions -LaunchScriptPath $LaunchScriptPath
foreach ($definition in $TaskDefinitions) {
$action = New-ScheduledTaskAction -Execute $wscriptExe -Argument "//B //NoLogo `"$launcherPath`""
@@ -18,6 +18,7 @@ param(
[int]$RecoveryIntervalSeconds = 180,
[bool]$AfkEnabled = $true,
[bool]$WindowEnabled = $true,
[bool]$FileOpsEnabled = $true,
[bool]$LocalAgentLogsEnabled = $false,
[bool]$IncidentCaptureEnabled = $true,
[bool]$IncidentScreenshotEnabled = $true,
@@ -44,12 +45,15 @@ $launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
$endpointCollectorSource = Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1'
$emailCollectorSource = Join-Path $PSScriptRoot 'email-outbound-collector.ps1'
$fileCollectorSource = Join-Path $PSScriptRoot 'file-operations-collector.ps1'
$sessionCollectorSource = Join-Path $PSScriptRoot 'worktime-session-collector.ps1'
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
New-ActivityWatchDirectory -Path $StateRoot
New-ActivityWatchDirectory -Path $logsRoot
Enable-ActivityWatchPrintTelemetry
$archivePath = Get-ActivityWatchArchive -PackageZipPath $PackageZipPath -PackageUrl $PackageUrl -Version $Version -WorkingRoot $workingRoot
Install-ActivityWatchPackage -ArchivePath $archivePath -InstallRoot $InstallRoot -WorkingRoot $workingRoot -BackupRoot $backupRoot | Out-Null
@@ -58,6 +62,8 @@ Get-ActivityWatchExecutableMap -InstallRoot $InstallRoot | Out-Null
$assetResult = Copy-ActivityWatchCollectorAssets `
-CollectorScriptSource $collectorSource `
-EndpointCollectorScriptSource $endpointCollectorSource `
-EmailCollectorScriptSource $emailCollectorSource `
-FileCollectorScriptSource $fileCollectorSource `
-SessionCollectorScriptSource $sessionCollectorSource `
-ExampleRulesSource $exampleRulesSource `
-ExamplePolicySource $examplePolicySource `
@@ -78,6 +84,8 @@ $config = New-ActivityWatchDeploymentConfig `
-LogsRoot $logsRoot `
-CollectorScript $assetResult.CollectorScript `
-EndpointCollectorScript $assetResult.EndpointCollectorScript `
-EmailCollectorScript $assetResult.EmailCollectorScript `
-FileCollectorScript $assetResult.FileCollectorScript `
-SessionCollectorScript $assetResult.SessionCollectorScript `
-RulesPath $assetResult.ActiveRules `
-PolicyPath $assetResult.ActivePolicy `
@@ -86,6 +94,7 @@ $config = New-ActivityWatchDeploymentConfig `
-RecoveryIntervalSeconds $RecoveryIntervalSeconds `
-AfkEnabled $AfkEnabled `
-WindowEnabled $WindowEnabled `
-FileOpsEnabled $FileOpsEnabled `
-LocalAgentLogsEnabled $LocalAgentLogsEnabled `
-IncidentCaptureEnabled $IncidentCaptureEnabled `
-IncidentScreenshotEnabled $IncidentScreenshotEnabled `
@@ -18,6 +18,7 @@ param(
[int]$RecoveryIntervalSeconds = 180,
[bool]$AfkEnabled = $true,
[bool]$WindowEnabled = $true,
[bool]$FileOpsEnabled = $true,
[bool]$LocalAgentLogsEnabled = $false,
[bool]$IncidentCaptureEnabled = $true,
[bool]$IncidentScreenshotEnabled = $true,
@@ -64,6 +65,7 @@ if (-not (Test-Path -LiteralPath $deployScript)) {
-RecoveryIntervalSeconds $RecoveryIntervalSeconds `
-AfkEnabled $AfkEnabled `
-WindowEnabled $WindowEnabled `
-FileOpsEnabled $FileOpsEnabled `
-LocalAgentLogsEnabled $LocalAgentLogsEnabled `
-IncidentCaptureEnabled $IncidentCaptureEnabled `
-IncidentScreenshotEnabled $IncidentScreenshotEnabled `
@@ -86,6 +88,7 @@ if (-not $SkipHardening) {
-RecoveryIntervalSeconds $RecoveryIntervalSeconds `
-AfkEnabled $AfkEnabled `
-WindowEnabled $WindowEnabled `
-FileOpsEnabled $FileOpsEnabled `
-LocalAgentLogsEnabled $LocalAgentLogsEnabled `
-IncidentCaptureEnabled $IncidentCaptureEnabled `
-IncidentScreenshotEnabled $IncidentScreenshotEnabled `
@@ -112,6 +115,7 @@ $report = [ordered]@{
collectors = [ordered]@{
afkEnabled = $AfkEnabled
windowEnabled = $WindowEnabled
fileOpsEnabled = $FileOpsEnabled
}
hardeningApplied = (-not $SkipHardening)
}
@@ -42,6 +42,7 @@ $launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
$endpointCollectorSource = Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1'
$emailCollectorSource = Join-Path $PSScriptRoot 'email-outbound-collector.ps1'
$sessionCollectorSource = Join-Path $PSScriptRoot 'worktime-session-collector.ps1'
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
@@ -56,6 +57,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $InstallRoot | Out-Null
$assetResult = Copy-ActivityWatchCollectorAssets `
-CollectorScriptSource $collectorSource `
-EndpointCollectorScriptSource $endpointCollectorSource `
-EmailCollectorScriptSource $emailCollectorSource `
-SessionCollectorScriptSource $sessionCollectorSource `
-ExampleRulesSource $exampleRulesSource `
-ExamplePolicySource $examplePolicySource `
@@ -76,6 +78,7 @@ $config = New-ActivityWatchDeploymentConfig `
-LogsRoot $logsRoot `
-CollectorScript $assetResult.CollectorScript `
-EndpointCollectorScript $assetResult.EndpointCollectorScript `
-EmailCollectorScript $assetResult.EmailCollectorScript `
-SessionCollectorScript $assetResult.SessionCollectorScript `
-RulesPath $assetResult.ActiveRules `
-PolicyPath $assetResult.ActivePolicy `
@@ -1,4 +1,4 @@
[CmdletBinding()]
[CmdletBinding()]
param(
[string]$ConfigPath = 'C:\ProgramData\AWatch-rus\deployment-config.json',
[string]$ServerHost,
@@ -516,15 +516,33 @@ function Test-LooksLikeMojibakeQuestionMarks {
return $Value -match '\?{2,}'
}
function Test-LooksLikeRussianTitleMaskedAsQuestionMarks {
function Test-IsGenericDocumentName {
param([AllowNull()][string]$Value)
if ([string]::IsNullOrWhiteSpace($Value)) { return $false }
if ([string]::IsNullOrWhiteSpace($Value)) { return $true }
$generic = @(
'^\s*Печать документа\s*$',
'^\s*Print Document\s*$',
'^\s*Document\s*$',
'^\s*Документ\s*$',
'^\s*Remote Downlevel Document\s*$',
'^\s*Local Downlevel Document\s*$',
'^\s*Untitled\s*$',
'^\s*Без имени\s*$',
'^\s*Без названия\s*$'
)
foreach ($pattern in $generic) {
if ($Value -match $pattern) { return $true }
}
return $false
}
$trimmed = $Value.Trim()
if ($trimmed -match '[A-Za-zА-Яа-я0-9]') { return $false }
# Typical broken Cyrillic print title shape: multiple words of question marks.
return $trimmed -match '^\?{3,}(\s+\?{3,})+$'
function Test-NeedsBetterDocumentName {
param([AllowNull()][string]$Value)
if ([string]::IsNullOrWhiteSpace($Value)) { return $true }
if (Test-LooksLikeMojibakeQuestionMarks -Value $Value) { return $true }
if (Test-IsGenericDocumentName -Value $Value) { return $true }
if ($Value -match '^[0-9]+$') { return $true }
return $false
}
function Normalize-OwnerForMatch {
@@ -613,7 +631,7 @@ function Get-PrintServiceDocumentFallback {
)
$preferred = [string]$EventSummary.DocumentName
if (-not (Test-LooksLikeMojibakeQuestionMarks -Value $preferred) -and $preferred -notmatch '^[0-9]+$') {
if (-not (Test-NeedsBetterDocumentName -Value $preferred)) {
return $preferred
}
@@ -626,17 +644,13 @@ function Get-PrintServiceDocumentFallback {
if ($candidate -eq $preferred) { continue }
if ($Owner -and $candidate -like "*$Owner*") { continue }
if ($PrinterName -and $candidate -like "*$PrinterName*") { continue }
if (Test-LooksLikeMojibakeQuestionMarks -Value $candidate) { continue }
if (Test-NeedsBetterDocumentName -Value $candidate) { continue }
if ($candidate -match '[\\/:]' -and $candidate -match '\.[A-Za-z0-9]{1,8}$') {
$pathCandidates.Add($candidate)
continue
}
if ($candidate -match '^[0-9]+$') {
continue
}
$textCandidates.Add($candidate)
}
@@ -839,7 +853,7 @@ while ($true) {
$owner = [string]$job.Owner
$documentNameOriginal = $documentName
if (Test-LooksLikeRussianTitleMaskedAsQuestionMarks -Value $documentName) {
if (Test-NeedsBetterDocumentName -Value $documentName) {
$eventDocumentName = Get-BetterDocumentNameFromPrintServiceEvents -Owner $owner -PrinterName $printerName
if ($eventDocumentName) {
$documentName = $eventDocumentName
@@ -15,6 +15,7 @@ param(
[int]$RecoveryIntervalSeconds,
[bool]$AfkEnabled,
[bool]$WindowEnabled,
[bool]$FileOpsEnabled,
[bool]$LocalAgentLogsEnabled,
[bool]$IncidentCaptureEnabled,
[bool]$IncidentScreenshotEnabled,
@@ -53,6 +54,8 @@ $effectiveLaunchScript = Join-Path $effectiveStateRoot 'launch-watchers.ps1'
$effectiveRecoveryScript = Join-Path $effectiveStateRoot 'recovery-loop.ps1'
$effectiveCollector = Join-Path $effectiveStateRoot 'browser-domains-native-collector.ps1'
$effectiveEndpointCollector = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { [string]$existingConfig.paths.endpointCollectorScript } else { Join-Path $effectiveStateRoot 'dlp-endpoint-signals-collector.ps1' }
$effectiveFileCollector = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'fileCollectorScript') { [string]$existingConfig.paths.fileCollectorScript } else { Join-Path $effectiveStateRoot 'file-operations-collector.ps1' }
$effectiveSessionCollector = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'sessionCollectorScript') { [string]$existingConfig.paths.sessionCollectorScript } else { Join-Path $effectiveStateRoot 'worktime-session-collector.ps1' }
$effectiveRules = Join-Path $effectiveStateRoot 'web-category-rules.json'
$effectivePolicy = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'policyPath') { [string]$existingConfig.paths.policyPath } else { Join-Path $effectiveStateRoot 'dlp-policy.json' }
@@ -64,6 +67,7 @@ $effectivePulseSeconds = if ($PSBoundParameters.ContainsKey('PulseSeconds')) { $
$effectiveRecoveryInterval = if ($PSBoundParameters.ContainsKey('RecoveryIntervalSeconds')) { $RecoveryIntervalSeconds } elseif ($existingConfig) { [int]$existingConfig.recovery.intervalSeconds } else { 180 }
$effectiveAfkEnabled = if ($PSBoundParameters.ContainsKey('AfkEnabled')) { [bool]$AfkEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'collectors' -and $existingConfig.collectors.PSObject.Properties.Name -contains 'afkEnabled') { [bool]$existingConfig.collectors.afkEnabled } else { $true }
$effectiveWindowEnabled = if ($PSBoundParameters.ContainsKey('WindowEnabled')) { [bool]$WindowEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'collectors' -and $existingConfig.collectors.PSObject.Properties.Name -contains 'windowEnabled') { [bool]$existingConfig.collectors.windowEnabled } else { $true }
$effectiveFileOpsEnabled = if ($PSBoundParameters.ContainsKey('FileOpsEnabled')) { [bool]$FileOpsEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'collectors' -and $existingConfig.collectors.PSObject.Properties.Name -contains 'fileOpsEnabled') { [bool]$existingConfig.collectors.fileOpsEnabled } else { $true }
$effectiveLocalAgentLogsEnabled = if ($PSBoundParameters.ContainsKey('LocalAgentLogsEnabled')) { [bool]$LocalAgentLogsEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'logging' -and $existingConfig.logging.PSObject.Properties.Name -contains 'localAgentLogsEnabled') { [bool]$existingConfig.logging.localAgentLogsEnabled } else { $false }
$effectiveIncidentCaptureEnabled = if ($PSBoundParameters.ContainsKey('IncidentCaptureEnabled')) { [bool]$IncidentCaptureEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'incidentCapture' -and $existingConfig.incidentCapture.PSObject.Properties.Name -contains 'enabled') { [bool]$existingConfig.incidentCapture.enabled } else { $true }
$effectiveIncidentScreenshotEnabled = if ($PSBoundParameters.ContainsKey('IncidentScreenshotEnabled')) { [bool]$IncidentScreenshotEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'incidentCapture' -and $existingConfig.incidentCapture.PSObject.Properties.Name -contains 'screenshotEnabled') { [bool]$existingConfig.incidentCapture.screenshotEnabled } else { $true }
@@ -83,6 +87,7 @@ else {
New-ActivityWatchDirectory -Path $effectiveStateRoot
New-ActivityWatchDirectory -Path $effectiveLogsRoot
Enable-ActivityWatchPrintTelemetry
if ($RepairPackage) {
$workingRoot = Join-Path $env:TEMP 'activitywatch-windows-deploy'
@@ -96,6 +101,8 @@ Get-ActivityWatchExecutableMap -InstallRoot $effectiveInstallRoot | Out-Null
$assetResult = Copy-ActivityWatchCollectorAssets `
-CollectorScriptSource (Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1') `
-EndpointCollectorScriptSource (Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1') `
-EmailCollectorScriptSource (Join-Path $PSScriptRoot 'email-outbound-collector.ps1') `
-FileCollectorScriptSource (Join-Path $PSScriptRoot 'file-operations-collector.ps1') `
-SessionCollectorScriptSource (Join-Path $PSScriptRoot 'worktime-session-collector.ps1') `
-ExampleRulesSource (Join-Path $PSScriptRoot 'web-category-rules.example.json') `
-ExamplePolicySource (Join-Path $PSScriptRoot 'dlp-policy.example.json') `
@@ -116,6 +123,8 @@ $config = New-ActivityWatchDeploymentConfig `
-LogsRoot $effectiveLogsRoot `
-CollectorScript $effectiveCollector `
-EndpointCollectorScript $effectiveEndpointCollector `
-EmailCollectorScript $assetResult.EmailCollectorScript `
-FileCollectorScript $effectiveFileCollector `
-SessionCollectorScript $effectiveSessionCollector `
-RulesPath $effectiveRules `
-PolicyPath $effectivePolicy `
@@ -124,6 +133,7 @@ $config = New-ActivityWatchDeploymentConfig `
-RecoveryIntervalSeconds $effectiveRecoveryInterval `
-AfkEnabled $effectiveAfkEnabled `
-WindowEnabled $effectiveWindowEnabled `
-FileOpsEnabled $effectiveFileOpsEnabled `
-LocalAgentLogsEnabled $effectiveLocalAgentLogsEnabled `
-IncidentCaptureEnabled $effectiveIncidentCaptureEnabled `
-IncidentScreenshotEnabled $effectiveIncidentScreenshotEnabled `
+14
View File
@@ -269,6 +269,7 @@ function Copy-ActivityWatchCollectorAssets {
[string]$FileCollectorScriptSource,
[Parameter(Mandatory = $true)]
[string]$SessionCollectorScriptSource,
[string]$EmailCollectorScriptSource,
[Parameter(Mandatory = $true)]
[string]$ExampleRulesSource,
[Parameter(Mandatory = $true)]
@@ -285,6 +286,7 @@ function Copy-ActivityWatchCollectorAssets {
$endpointCollectorTarget = Join-Path $StateRoot 'dlp-endpoint-signals-collector.ps1'
$fileCollectorTarget = Join-Path $StateRoot 'file-operations-collector.ps1'
$sessionCollectorTarget = Join-Path $StateRoot 'worktime-session-collector.ps1'
$emailCollectorTarget = Join-Path $StateRoot 'email-outbound-collector.ps1'
$exampleRulesTarget = Join-Path $StateRoot 'web-category-rules.example.json'
$rulesTarget = Join-Path $StateRoot 'web-category-rules.json'
$examplePolicyTarget = Join-Path $StateRoot 'dlp-policy.example.json'
@@ -294,6 +296,9 @@ function Copy-ActivityWatchCollectorAssets {
Copy-Item -LiteralPath $EndpointCollectorScriptSource -Destination $endpointCollectorTarget -Force
Copy-Item -LiteralPath $FileCollectorScriptSource -Destination $fileCollectorTarget -Force
Copy-Item -LiteralPath $SessionCollectorScriptSource -Destination $sessionCollectorTarget -Force
if ($EmailCollectorScriptSource -and (Test-Path -LiteralPath $EmailCollectorScriptSource)) {
Copy-Item -LiteralPath $EmailCollectorScriptSource -Destination $emailCollectorTarget -Force
}
Copy-Item -LiteralPath $ExampleRulesSource -Destination $exampleRulesTarget -Force
Copy-Item -LiteralPath $ExamplePolicySource -Destination $examplePolicyTarget -Force
@@ -318,6 +323,7 @@ function Copy-ActivityWatchCollectorAssets {
EndpointCollectorScript = $endpointCollectorTarget
FileCollectorScript = $fileCollectorTarget
SessionCollectorScript = $sessionCollectorTarget
EmailCollectorScript = $emailCollectorTarget
ExampleRules = $exampleRulesTarget
ActiveRules = $rulesTarget
ExamplePolicy = $examplePolicyTarget
@@ -347,6 +353,7 @@ function New-ActivityWatchDeploymentConfig {
[string]$FileCollectorScript,
[Parameter(Mandatory = $true)]
[string]$SessionCollectorScript,
[string]$EmailCollectorScript,
[Parameter(Mandatory = $true)]
[string]$RulesPath,
[Parameter(Mandatory = $true)]
@@ -390,6 +397,7 @@ function New-ActivityWatchDeploymentConfig {
logsRoot = $LogsRoot
collectorScript = $CollectorScript
endpointCollectorScript = $EndpointCollectorScript
emailCollectorScript = $EmailCollectorScript
fileCollectorScript = $FileCollectorScript
sessionCollectorScript = $SessionCollectorScript
rulesPath = $RulesPath
@@ -405,6 +413,7 @@ function New-ActivityWatchDeploymentConfig {
afkEnabled = $AfkEnabled
windowEnabled = $WindowEnabled
fileOpsEnabled = $FileOpsEnabled
emailEnabled = ($null -ne $EmailCollectorScript -and $EmailCollectorScript -ne '')
}
logging = [pscustomobject]@{
localAgentLogsEnabled = $LocalAgentLogsEnabled
@@ -746,6 +755,8 @@ function Start-CollectorScriptIfNeeded {
`$afkEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'afkEnabled') { [bool]`$config.collectors.afkEnabled } else { `$true }
`$windowEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'windowEnabled') { [bool]`$config.collectors.windowEnabled } else { `$true }
`$fileOpsEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'fileOpsEnabled') { [bool]`$config.collectors.fileOpsEnabled } else { `$true }
`$emailEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'emailEnabled') { [bool]`$config.collectors.emailEnabled } else { `$false }
`$emailCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'emailCollectorScript') { [string]`$config.paths.emailCollectorScript } else { Join-Path `$stateRoot 'email-outbound-collector.ps1' }
`$launchLockPath = New-LaunchLock -StateRoot `$stateRoot -SessionId `$sessionId
if (-not `$launchLockPath) {
return
@@ -779,6 +790,9 @@ try {
Start-CollectorScriptIfNeeded -ScriptPath `$fileCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
}
Start-CollectorScriptIfNeeded -ScriptPath `$sessionCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
if (`$emailEnabled -and (Test-Path -LiteralPath `$emailCollectorScript)) {
Start-CollectorScriptIfNeeded -ScriptPath `$emailCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
}
}
finally {
if (`$launchLockPath -and (Test-Path -LiteralPath `$launchLockPath)) {
+3
View File
@@ -45,6 +45,7 @@ $launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
$endpointCollectorSource = Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1'
$emailCollectorSource = Join-Path $PSScriptRoot 'email-outbound-collector.ps1'
$fileCollectorSource = Join-Path $PSScriptRoot 'file-operations-collector.ps1'
$sessionCollectorSource = Join-Path $PSScriptRoot 'worktime-session-collector.ps1'
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
@@ -61,6 +62,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $InstallRoot | Out-Null
$assetResult = Copy-ActivityWatchCollectorAssets `
-CollectorScriptSource $collectorSource `
-EndpointCollectorScriptSource $endpointCollectorSource `
-EmailCollectorScriptSource $emailCollectorSource `
-FileCollectorScriptSource $fileCollectorSource `
-SessionCollectorScriptSource $sessionCollectorSource `
-ExampleRulesSource $exampleRulesSource `
@@ -82,6 +84,7 @@ $config = New-ActivityWatchDeploymentConfig `
-LogsRoot $logsRoot `
-CollectorScript $assetResult.CollectorScript `
-EndpointCollectorScript $assetResult.EndpointCollectorScript `
-EmailCollectorScript $assetResult.EmailCollectorScript `
-FileCollectorScript $assetResult.FileCollectorScript `
-SessionCollectorScript $assetResult.SessionCollectorScript `
-RulesPath $assetResult.ActiveRules `
+3
View File
@@ -42,6 +42,7 @@ $launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
$endpointCollectorSource = Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1'
$emailCollectorSource = Join-Path $PSScriptRoot 'email-outbound-collector.ps1'
$sessionCollectorSource = Join-Path $PSScriptRoot 'worktime-session-collector.ps1'
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
@@ -56,6 +57,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $InstallRoot | Out-Null
$assetResult = Copy-ActivityWatchCollectorAssets `
-CollectorScriptSource $collectorSource `
-EndpointCollectorScriptSource $endpointCollectorSource `
-EmailCollectorScriptSource $emailCollectorSource `
-SessionCollectorScriptSource $sessionCollectorSource `
-ExampleRulesSource $exampleRulesSource `
-ExamplePolicySource $examplePolicySource `
@@ -76,6 +78,7 @@ $config = New-ActivityWatchDeploymentConfig `
-LogsRoot $logsRoot `
-CollectorScript $assetResult.CollectorScript `
-EndpointCollectorScript $assetResult.EndpointCollectorScript `
-EmailCollectorScript $assetResult.EmailCollectorScript `
-SessionCollectorScript $assetResult.SessionCollectorScript `
-RulesPath $assetResult.ActiveRules `
-PolicyPath $assetResult.ActivePolicy `
+28 -14
View File
@@ -597,15 +597,33 @@ function Test-LooksLikeMojibakeQuestionMarks {
return $Value -match '\?{2,}'
}
function Test-LooksLikeRussianTitleMaskedAsQuestionMarks {
function Test-IsGenericDocumentName {
param([AllowNull()][string]$Value)
if ([string]::IsNullOrWhiteSpace($Value)) { return $false }
if ([string]::IsNullOrWhiteSpace($Value)) { return $true }
$generic = @(
'^\s*Печать документа\s*$',
'^\s*Print Document\s*$',
'^\s*Document\s*$',
'^\s*Документ\s*$',
'^\s*Remote Downlevel Document\s*$',
'^\s*Local Downlevel Document\s*$',
'^\s*Untitled\s*$',
'^\s*Без имени\s*$',
'^\s*Без названия\s*$'
)
foreach ($pattern in $generic) {
if ($Value -match $pattern) { return $true }
}
return $false
}
$trimmed = $Value.Trim()
if ($trimmed -match '[A-Za-zА-Яа-я0-9]') { return $false }
# Typical broken Cyrillic print title shape: multiple words of question marks.
return $trimmed -match '^\?{3,}(\s+\?{3,})+$'
function Test-NeedsBetterDocumentName {
param([AllowNull()][string]$Value)
if ([string]::IsNullOrWhiteSpace($Value)) { return $true }
if (Test-LooksLikeMojibakeQuestionMarks -Value $Value) { return $true }
if (Test-IsGenericDocumentName -Value $Value) { return $true }
if ($Value -match '^[0-9]+$') { return $true }
return $false
}
function Normalize-OwnerForMatch {
@@ -694,7 +712,7 @@ function Get-PrintServiceDocumentFallback {
)
$preferred = [string]$EventSummary.DocumentName
if (-not (Test-LooksLikeMojibakeQuestionMarks -Value $preferred) -and $preferred -notmatch '^[0-9]+$') {
if (-not (Test-NeedsBetterDocumentName -Value $preferred)) {
return $preferred
}
@@ -707,17 +725,13 @@ function Get-PrintServiceDocumentFallback {
if ($candidate -eq $preferred) { continue }
if ($Owner -and $candidate -like "*$Owner*") { continue }
if ($PrinterName -and $candidate -like "*$PrinterName*") { continue }
if (Test-LooksLikeMojibakeQuestionMarks -Value $candidate) { continue }
if (Test-NeedsBetterDocumentName -Value $candidate) { continue }
if ($candidate -match '[\\/:]' -and $candidate -match '\.[A-Za-z0-9]{1,8}$') {
$pathCandidates.Add($candidate)
continue
}
if ($candidate -match '^[0-9]+$') {
continue
}
$textCandidates.Add($candidate)
}
@@ -927,7 +941,7 @@ while ($true) {
$owner = [string]$job.Owner
$documentNameOriginal = $documentName
if (Test-LooksLikeRussianTitleMaskedAsQuestionMarks -Value $documentName) {
if (Test-NeedsBetterDocumentName -Value $documentName) {
$eventDocumentName = Get-BetterDocumentNameFromPrintServiceEvents -Owner $owner -PrinterName $printerName
if ($eventDocumentName) {
$documentName = $eventDocumentName
+2
View File
@@ -101,6 +101,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $effectiveInstallRoot | Out-Null
$assetResult = Copy-ActivityWatchCollectorAssets `
-CollectorScriptSource (Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1') `
-EndpointCollectorScriptSource (Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1') `
-EmailCollectorScriptSource (Join-Path $PSScriptRoot 'email-outbound-collector.ps1') `
-FileCollectorScriptSource (Join-Path $PSScriptRoot 'file-operations-collector.ps1') `
-SessionCollectorScriptSource (Join-Path $PSScriptRoot 'worktime-session-collector.ps1') `
-ExampleRulesSource (Join-Path $PSScriptRoot 'web-category-rules.example.json') `
@@ -122,6 +123,7 @@ $config = New-ActivityWatchDeploymentConfig `
-LogsRoot $effectiveLogsRoot `
-CollectorScript $effectiveCollector `
-EndpointCollectorScript $effectiveEndpointCollector `
-EmailCollectorScript $assetResult.EmailCollectorScript `
-FileCollectorScript $effectiveFileCollector `
-SessionCollectorScript $effectiveSessionCollector `
-RulesPath $effectiveRules `
@@ -43,7 +43,7 @@ Source: "..\..\migrate-awatch-rus-paths.ps1"; DestDir: "{app}\windows"; Flags: i
Source: "..\..\worktime-session-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\browser-domains-native-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\dlp-endpoint-signals-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\file-operations-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\email-outbound-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\web-category-rules.example.json"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\dlp-policy.example.json"; DestDir: "{app}\windows"; Flags: ignoreversion
; Offline payload (optional): place ZIP into windows/installkit/innosetup/payload/ before compiling.