param( [Parameter(Mandatory = $true)] [string]$EnrollmentToken, [string]$ServerUrl = "https://manage.fineit.com.au", [switch]$AllowDeviceChanges, [switch]$AllowActivitySnapshots, [switch]$AllowRemoteControl ) $ErrorActionPreference = "Stop" $installRoot = "C:\ProgramData\FineITEndpointAgent" $agentDir = Join-Path $installRoot "agent" $agentFile = Join-Path $agentDir "index.js" $configFile = Join-Path $installRoot "agent-config.json" $runnerFile = Join-Path $installRoot "run-agent.ps1" $remoteRunnerFile = Join-Path $installRoot "run-agent-remote.ps1" $taskName = "FineIT Endpoint Agent" $remoteTaskName = "FineIT Endpoint Agent Remote Control" function Assert-Admin { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Run this installer from an elevated PowerShell window." } } function Ensure-Node { $node = Get-Command node.exe -ErrorAction SilentlyContinue if ($node) { return $node.Source } $winget = Get-Command winget.exe -ErrorAction SilentlyContinue if (-not $winget) { throw "Node.js is not installed and winget is not available. Install Node.js LTS from https://nodejs.org, then rerun this installer." } winget install --exact --id OpenJS.NodeJS.LTS --silent --accept-package-agreements --accept-source-agreements $env:Path = [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [Environment]::GetEnvironmentVariable("Path", "User") $node = Get-Command node.exe -ErrorAction SilentlyContinue if (-not $node) { throw "Node.js install completed, but node.exe was not found. Restart PowerShell and rerun this installer." } return $node.Source } Assert-Admin $nodePath = Ensure-Node New-Item -ItemType Directory -Force -Path $agentDir | Out-Null Invoke-WebRequest -Uri "$ServerUrl/downloads/agent/index.js" -OutFile $agentFile -UseBasicParsing $env:SERVER_BASE_URL = $ServerUrl $env:ENROLLMENT_TOKEN = $EnrollmentToken $env:AGENT_CONFIG = $configFile $env:AGENT_ONCE = "true" & $nodePath $agentFile if ($LASTEXITCODE -ne 0) { throw "Agent enrollment failed." } $allowDeviceChangesValue = if ($AllowDeviceChanges) { "true" } else { "false" } $allowActivitySnapshotsValue = if ($AllowActivitySnapshots) { "true" } else { "false" } $runner = @( '$env:SERVER_BASE_URL = "' + $ServerUrl + '"', '$env:AGENT_CONFIG = "' + $configFile + '"', '$env:ALLOW_DEVICE_CHANGES = "' + $allowDeviceChangesValue + '"', '$env:ALLOW_ACTIVITY_SNAPSHOTS = "' + $allowActivitySnapshotsValue + '"', '$env:ALLOW_REMOTE_CONTROL = "false"', '$env:ACTIVITY_DIR = "C:\ProgramData\FineITEndpointAgent\activity"', '& "' + $nodePath + '" "' + $agentFile + '"' ) -join [Environment]::NewLine Set-Content -Path $runnerFile -Value $runner -Encoding UTF8 $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument ('-NoProfile -ExecutionPolicy Bypass -File "' + $runnerFile + '"') $trigger = New-ScheduledTaskTrigger -AtStartup $settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -AllowStartIfOnBatteries -ExecutionTimeLimit (New-TimeSpan -Days 0) Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Settings $settings -User "SYSTEM" -RunLevel Highest -Force | Out-Null Start-ScheduledTask -TaskName $taskName if ($AllowRemoteControl) { $remoteRunner = @( '$env:SERVER_BASE_URL = "' + $ServerUrl + '"', '$env:AGENT_CONFIG = "' + $configFile + '"', '$env:ALLOW_REMOTE_CONTROL = "true"', '& "' + $nodePath + '" "' + $agentFile + '"' ) -join [Environment]::NewLine Set-Content -Path $remoteRunnerFile -Value $remoteRunner -Encoding UTF8 $userId = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $remoteAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument ('-NoProfile -ExecutionPolicy Bypass -File "' + $remoteRunnerFile + '"') $remoteTrigger = New-ScheduledTaskTrigger -AtLogOn -User $userId $remotePrincipal = New-ScheduledTaskPrincipal -UserId $userId -LogonType Interactive -RunLevel Highest Register-ScheduledTask -TaskName $remoteTaskName -Action $remoteAction -Trigger $remoteTrigger -Principal $remotePrincipal -Force | Out-Null Start-ScheduledTask -TaskName $remoteTaskName } Write-Host "FineIT Endpoint Agent installed and started." Write-Host "Server: $ServerUrl" Write-Host "Config: $configFile"