89 lines
3.4 KiB
PowerShell
89 lines
3.4 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string]$ConfigPath = 'C:\ProgramData\AWatch-rus\deployment-config.json',
|
|
[ValidateSet('shadow', 'enforce')]
|
|
[string]$Mode = 'shadow',
|
|
[string]$ServiceName = 'AWatchRusCollectorGuard',
|
|
[int]$LoopSeconds = 60,
|
|
[switch]$DisableRecoveryTask
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
function Assert-Admin {
|
|
$id = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$principal = [Security.Principal.WindowsPrincipal]::new($id)
|
|
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
throw 'Run as Administrator.'
|
|
}
|
|
}
|
|
|
|
Assert-Admin
|
|
|
|
$guardScriptPath = Join-Path $PSScriptRoot 'aw-collector-guard.ps1'
|
|
$serviceSourcePath = Join-Path $PSScriptRoot 'AWatchRusCollectorGuardService.cs'
|
|
$serviceExePath = Join-Path $PSScriptRoot 'AWatchRusCollectorGuardService.exe'
|
|
if (-not (Test-Path -LiteralPath $guardScriptPath)) {
|
|
throw "Collector guard script not found: $guardScriptPath"
|
|
}
|
|
if (-not (Test-Path -LiteralPath $serviceSourcePath)) {
|
|
throw "Collector guard service source not found: $serviceSourcePath"
|
|
}
|
|
if (-not (Test-Path -LiteralPath $ConfigPath)) {
|
|
throw "Config not found: $ConfigPath"
|
|
}
|
|
|
|
$cscCandidates = @(
|
|
(Join-Path $env:WINDIR 'Microsoft.NET\Framework64\v4.0.30319\csc.exe'),
|
|
(Join-Path $env:WINDIR 'Microsoft.NET\Framework\v4.0.30319\csc.exe')
|
|
)
|
|
$csc = @($cscCandidates | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1)
|
|
if (-not $csc) {
|
|
throw 'C# compiler not found. Install .NET Framework build tools or provide AWatchRusCollectorGuardService.exe.'
|
|
}
|
|
|
|
$existing = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
if ($existing) {
|
|
if ($existing.Status -ne 'Stopped') {
|
|
Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
|
|
try {
|
|
$existing.WaitForStatus('Stopped', [TimeSpan]::FromSeconds(20))
|
|
}
|
|
catch {
|
|
}
|
|
}
|
|
sc.exe delete $ServiceName | Out-Null
|
|
Start-Sleep -Seconds 2
|
|
}
|
|
|
|
& $csc /nologo /target:exe /optimize+ /out:$serviceExePath /reference:System.ServiceProcess.dll $serviceSourcePath | Out-Null
|
|
if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $serviceExePath)) {
|
|
throw "Failed to compile $serviceExePath"
|
|
}
|
|
|
|
$logsRoot = Join-Path (Split-Path -Path $ConfigPath -Parent) 'logs'
|
|
$serviceLogPath = Join-Path $logsRoot 'collector-guard-service.log'
|
|
$binPath = "`"$serviceExePath`" --service-name `"$ServiceName`" --script `"$guardScriptPath`" --config `"$ConfigPath`" --mode $Mode --loop $LoopSeconds --log `"$serviceLogPath`""
|
|
|
|
New-Service -Name $ServiceName -BinaryPathName $binPath -DisplayName 'AWatch-rus Collector Guard' -StartupType Automatic | Out-Null
|
|
sc.exe description $ServiceName "Session-aware ActivityWatch collector guard for AWatch-rus" | Out-Null
|
|
sc.exe failure $ServiceName reset= 300 actions= restart/5000/restart/15000/restart/60000 | Out-Null
|
|
|
|
if ($DisableRecoveryTask) {
|
|
Write-Warning 'DisableRecoveryTask is deprecated and ignored: ActivityWatch Recovery must remain enabled as collector guard fallback.'
|
|
}
|
|
else {
|
|
try {
|
|
Enable-ScheduledTask -TaskName 'ActivityWatch Recovery' -ErrorAction SilentlyContinue | Out-Null
|
|
}
|
|
catch {
|
|
}
|
|
}
|
|
|
|
sc.exe start $ServiceName | Out-Null
|
|
|
|
Write-Output "Collector guard service installed: $ServiceName"
|
|
Write-Output "Mode: $Mode"
|
|
Write-Output "Config: $ConfigPath"
|