You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
8.3 KiB
239 lines
8.3 KiB
# GeoNetAgent - Install atau update ke %ProgramData%\GeoNetAgent |
|
# Unduh dari https://agent.gisportal.id/install atau -SourcePath lokal |
|
[CmdletBinding()] |
|
param( |
|
[string]$BaseUrl = 'https://agent.gisportal.id/install', |
|
[string]$InstallRoot = (Join-Path $env:ProgramData 'GeoNetAgent'), |
|
[string]$AgentToken, |
|
[string]$SourcePath, |
|
[switch]$SkipScheduledTask, |
|
[switch]$SkipInitialRun, |
|
[int]$ScheduleHours = 6 |
|
) |
|
|
|
$ErrorActionPreference = 'Stop' |
|
|
|
function Test-GeoNetAdmin { |
|
$id = [Security.Principal.WindowsIdentity]::GetCurrent() |
|
$p = New-Object Security.Principal.WindowsPrincipal($id) |
|
return $p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) |
|
} |
|
|
|
function Get-GeoNetInstallBaseUrl { |
|
param([string]$Url) |
|
return $Url.TrimEnd('/') |
|
} |
|
|
|
function Get-GeoNetRemoteJson { |
|
param([string]$Url) |
|
return (Invoke-WebRequest -Uri $Url -UseBasicParsing).Content | ConvertFrom-Json |
|
} |
|
|
|
function Get-GeoNetRemoteFile { |
|
param([string]$Url, [string]$Destination) |
|
$parent = Split-Path -Parent $Destination |
|
if (-not (Test-Path $parent)) { |
|
New-Item -ItemType Directory -Path $parent -Force | Out-Null |
|
} |
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 |
|
$lastErr = $null |
|
for ($try = 1; $try -le 3; $try++) { |
|
try { |
|
Invoke-WebRequest -Uri $Url -OutFile $Destination -UseBasicParsing -TimeoutSec 90 |
|
if ((Get-Item $Destination).Length -gt 0) { return } |
|
} |
|
catch { |
|
$lastErr = $_ |
|
Start-Sleep -Seconds 2 |
|
} |
|
} |
|
if (Get-Command curl.exe -ErrorAction SilentlyContinue) { |
|
& curl.exe -fsSL --tlsv1.2 $Url -o $Destination |
|
if ($LASTEXITCODE -eq 0 -and (Test-Path $Destination)) { return } |
|
} |
|
throw $lastErr |
|
} |
|
|
|
function Copy-GeoNetAgentPayload { |
|
param( |
|
[string]$SourceRoot, |
|
[string]$DestinationRoot, |
|
[object]$Manifest |
|
) |
|
foreach ($rel in $Manifest.files) { |
|
$src = Join-Path $SourceRoot ($rel -replace '/', [IO.Path]::DirectorySeparatorChar) |
|
$dst = Join-Path $DestinationRoot ($rel -replace '/', [IO.Path]::DirectorySeparatorChar) |
|
if (-not (Test-Path $src)) { |
|
throw "File sumber tidak ada: $src" |
|
} |
|
$dir = Split-Path -Parent $dst |
|
if (-not (Test-Path $dir)) { |
|
New-Item -ItemType Directory -Path $dir -Force | Out-Null |
|
} |
|
Copy-Item -Path $src -Destination $dst -Force |
|
} |
|
} |
|
|
|
function Install-GeoNetAgentPayload { |
|
param( |
|
[string]$Base, |
|
[string]$DestinationRoot, |
|
[object]$Manifest |
|
) |
|
foreach ($rel in $Manifest.files) { |
|
$url = "$Base/$($rel -replace '\\', '/')" |
|
$dst = Join-Path $DestinationRoot ($rel -replace '/', [IO.Path]::DirectorySeparatorChar) |
|
Write-Host " -> $rel" |
|
Get-GeoNetRemoteFile -Url $url -Destination $dst |
|
} |
|
} |
|
|
|
function Set-GeoNetAgentConfig { |
|
param( |
|
[string]$InstallRoot, |
|
[string]$Base, |
|
[string]$Token, |
|
[bool]$UseRemoteConfig |
|
) |
|
$configPath = Join-Path $InstallRoot 'config.json' |
|
|
|
if ($Token) { |
|
$cfg = [ordered]@{ |
|
collector_url = 'https://agent.gisportal.id/api/v1/agent/report' |
|
agent_token = $Token |
|
include_software = $true |
|
max_software = 500 |
|
timeout_seconds = 120 |
|
} |
|
if (Test-Path $configPath) { |
|
try { |
|
$existing = Get-Content $configPath -Raw | ConvertFrom-Json |
|
if ($existing.collector_url) { $cfg.collector_url = $existing.collector_url } |
|
if ($null -ne $existing.include_software) { $cfg.include_software = [bool]$existing.include_software } |
|
if ($existing.max_software) { $cfg.max_software = [int]$existing.max_software } |
|
if ($existing.timeout_seconds) { $cfg.timeout_seconds = [int]$existing.timeout_seconds } |
|
} |
|
catch { } |
|
} |
|
$cfg | ConvertTo-Json | Set-Content -Path $configPath -Encoding UTF8 |
|
return |
|
} |
|
|
|
if ((Test-Path $configPath) -and -not $UseRemoteConfig) { |
|
Write-Host 'config.json lokal dipertahankan.' -ForegroundColor DarkGray |
|
return |
|
} |
|
|
|
if ($UseRemoteConfig) { |
|
Get-GeoNetRemoteFile -Url "$Base/config.json" -Destination $configPath |
|
return |
|
} |
|
|
|
throw 'config.json tidak ada. Sediakan -AgentToken atau config.json di URL install.' |
|
} |
|
|
|
function Invoke-GeoNetSchtasks { |
|
param( |
|
[Parameter(Mandatory)][string[]]$ArgumentList, |
|
[switch]$IgnoreError |
|
) |
|
$prev = $ErrorActionPreference |
|
$ErrorActionPreference = 'SilentlyContinue' |
|
$output = & schtasks.exe @ArgumentList 2>&1 |
|
$code = $LASTEXITCODE |
|
$ErrorActionPreference = $prev |
|
if ($code -ne 0 -and -not $IgnoreError) { |
|
$msg = ($output | Out-String).Trim() |
|
if ($msg) { throw $msg } |
|
throw "schtasks gagal (exit $code): schtasks.exe $($ArgumentList -join ' ')" |
|
} |
|
return $code |
|
} |
|
|
|
function Register-GeoNetAgentTask { |
|
param( |
|
[string]$InstallRoot, |
|
[int]$Hours |
|
) |
|
$userScript = Join-Path $InstallRoot 'UserAgent.ps1' |
|
if (-not (Test-Path $userScript)) { |
|
throw "UserAgent.ps1 tidak ditemukan di $InstallRoot" |
|
} |
|
|
|
$taskArgs = "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$userScript`"" |
|
$taskCmd = "powershell.exe $taskArgs" |
|
$taskNames = @('GeoNetAgent-Report', 'GeoNetAgent-Report-Startup') |
|
|
|
foreach ($name in $taskNames) { |
|
Unregister-ScheduledTask -TaskName $name -Confirm:$false -ErrorAction SilentlyContinue |
|
Invoke-GeoNetSchtasks -ArgumentList @('/Delete', '/TN', $name, '/F') -IgnoreError | Out-Null |
|
} |
|
|
|
Invoke-GeoNetSchtasks -ArgumentList @( |
|
'/Create', '/TN', 'GeoNetAgent-Report-Startup', '/TR', $taskCmd, |
|
'/SC', 'ONSTART', '/RU', 'SYSTEM', '/RL', 'HIGHEST', '/F' |
|
) | Out-Null |
|
|
|
Invoke-GeoNetSchtasks -ArgumentList @( |
|
'/Create', '/TN', 'GeoNetAgent-Report', '/TR', $taskCmd, |
|
'/SC', 'HOURLY', '/MO', "$Hours", '/RU', 'SYSTEM', '/RL', 'HIGHEST', '/F' |
|
) | Out-Null |
|
} |
|
|
|
$base = Get-GeoNetInstallBaseUrl -Url $BaseUrl |
|
Write-Host "GeoNetAgent install/update" -ForegroundColor Cyan |
|
Write-Host " Target: $InstallRoot" |
|
|
|
if (-not (Test-Path $InstallRoot)) { |
|
New-Item -ItemType Directory -Path $InstallRoot -Force | Out-Null |
|
} |
|
|
|
if ($SourcePath) { |
|
$sourceRoot = Resolve-Path $SourcePath |
|
$manifestPath = Join-Path $sourceRoot 'install\manifest.json' |
|
if (-not (Test-Path $manifestPath)) { |
|
$manifestPath = Join-Path $sourceRoot 'manifest.json' |
|
} |
|
if (-not (Test-Path $manifestPath)) { |
|
throw "manifest.json tidak ditemukan di $SourcePath" |
|
} |
|
$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json |
|
Write-Host "Salin dari lokal v$($manifest.version) ..." |
|
Copy-GeoNetAgentPayload -SourceRoot $sourceRoot -DestinationRoot $InstallRoot -Manifest $manifest |
|
Set-GeoNetAgentConfig -InstallRoot $InstallRoot -Base $base -Token $AgentToken -UseRemoteConfig:$false |
|
} |
|
else { |
|
Write-Host "Unduh dari $base ..." |
|
$manifest = Get-GeoNetRemoteJson -Url "$base/manifest.json" |
|
Write-Host "Paket v$($manifest.version) ($($manifest.files.Count) file)" |
|
Install-GeoNetAgentPayload -Base $base -DestinationRoot $InstallRoot -Manifest $manifest |
|
$remoteConfig = $false |
|
try { |
|
$null = Invoke-WebRequest -Uri "$base/config.json" -Method Head -UseBasicParsing |
|
$remoteConfig = $true |
|
} |
|
catch { } |
|
Set-GeoNetAgentConfig -InstallRoot $InstallRoot -Base $base -Token $AgentToken -UseRemoteConfig:$remoteConfig |
|
} |
|
|
|
$manifest.version | Set-Content -Path (Join-Path $InstallRoot 'VERSION') -Encoding ASCII -NoNewline |
|
|
|
if (-not $SkipScheduledTask) { |
|
if (-not (Test-GeoNetAdmin)) { |
|
Write-Warning 'Bukan Administrator - file terpasang, tetapi Scheduled Task dilewati. Jalankan ulang sebagai Admin.' |
|
} |
|
else { |
|
Write-Host 'Mendaftarkan Scheduled Task (SYSTEM: startup + tiap' $ScheduleHours 'jam) ...' |
|
Register-GeoNetAgentTask -InstallRoot $InstallRoot -Hours $ScheduleHours |
|
Write-Host 'Scheduled Task OK: GeoNetAgent-Report, GeoNetAgent-Report-Startup' -ForegroundColor Green |
|
} |
|
} |
|
|
|
if (-not $SkipInitialRun) { |
|
Write-Host 'Menjalankan laporan awal ...' -ForegroundColor Cyan |
|
& (Join-Path $InstallRoot 'UserAgent.ps1') |
|
exit $LASTEXITCODE |
|
} |
|
|
|
Write-Host 'Selesai.' -ForegroundColor Green |
|
exit 0
|
|
|