Merge pull request #15 from igor04091968/devin/1777897921-print-docname-ansible-innosetup
fix(print): исправление имени документа «Печать документа» + интеграция email collector в деплой
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
@@ -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",
|
||||
|
||||
+1
@@ -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",
|
||||
|
||||
+1
@@ -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 `
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 `
|
||||
|
||||
@@ -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 `
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user