Initial commit: IT Nexus Web-App
This commit is contained in:
524
agent/IT-Nexus-Agent-Setup.hta
Normal file
524
agent/IT-Nexus-Agent-Setup.hta
Normal file
@@ -0,0 +1,524 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=11">
|
||||
<title>IT Nexus Agent Setup</title>
|
||||
<HTA:APPLICATION
|
||||
APPLICATIONNAME="IT Nexus Agent Setup"
|
||||
BORDER="thin"
|
||||
BORDERSTYLE="normal"
|
||||
CAPTION="yes"
|
||||
CONTEXTMENU="no"
|
||||
MAXIMIZEBUTTON="no"
|
||||
MINIMIZEBUTTON="yes"
|
||||
NAVIGABLE="no"
|
||||
SCROLL="no"
|
||||
SELECTION="no"
|
||||
SHOWINTASKBAR="yes"
|
||||
SINGLEINSTANCE="yes"
|
||||
SYSMENU="yes"
|
||||
WINDOWSTATE="normal"
|
||||
/>
|
||||
<style>
|
||||
* { margin:0; padding:0; box-sizing:border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, sans-serif;
|
||||
background: #1e1e2e;
|
||||
color: #cdd6f4;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
position: absolute;
|
||||
left: 0; top: 0; bottom: 0;
|
||||
width: 220px;
|
||||
background: #181825;
|
||||
border-right: 1px solid #313244;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 28px 0 20px;
|
||||
}
|
||||
|
||||
.sidebar-logo {
|
||||
padding: 0 20px 28px;
|
||||
border-bottom: 1px solid #313244;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.sidebar-logo-title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #cdd6f4;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.sidebar-logo-sub {
|
||||
font-size: 14px;
|
||||
color: #6c7086;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 13px 20px;
|
||||
font-size: 16px;
|
||||
color: #6c7086;
|
||||
cursor: default;
|
||||
}
|
||||
.nav-item.done { color: #a6e3a1; }
|
||||
.nav-item.active { color: #89b4fa; font-weight: 600; background: rgba(137,180,250,0.08); border-right: 3px solid #89b4fa; }
|
||||
|
||||
.nav-num {
|
||||
width: 28px; height: 28px;
|
||||
border-radius: 50%;
|
||||
font-size: 13px; font-weight: 700;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
background: #313244;
|
||||
color: #6c7086;
|
||||
}
|
||||
.nav-item.done .nav-num { background: #a6e3a1; color: #1e1e2e; }
|
||||
.nav-item.active .nav-num { background: #89b4fa; color: #1e1e2e; }
|
||||
|
||||
/* Main */
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 220px; top: 0; right: 0; bottom: 60px;
|
||||
padding: 36px 36px 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.step { display: none; }
|
||||
.step.active { display: block; }
|
||||
|
||||
.step-title {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #cdd6f4;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.step-subtitle {
|
||||
font-size: 16px;
|
||||
color: #6c7086;
|
||||
margin-bottom: 28px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Feature list */
|
||||
.feature-list { list-style: none; }
|
||||
.feature-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #313244;
|
||||
font-size: 17px;
|
||||
}
|
||||
.feature-item:last-child { border-bottom: none; }
|
||||
.feature-dot {
|
||||
width: 10px; height: 10px;
|
||||
border-radius: 50%;
|
||||
background: #89b4fa;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Fields */
|
||||
.field { margin-bottom: 14px; }
|
||||
.field label {
|
||||
font-size: 14px;
|
||||
color: #6c7086;
|
||||
display: block;
|
||||
margin-bottom: 7px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.field input {
|
||||
width: 100%;
|
||||
padding: 12px 14px;
|
||||
background: #181825;
|
||||
border: 1px solid #313244;
|
||||
border-radius: 6px;
|
||||
color: #cdd6f4;
|
||||
font-size: 16px;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
transition: border-color .15s;
|
||||
}
|
||||
.field input:focus { outline: none; border-color: #89b4fa; }
|
||||
.field input[readonly] { color: #6c7086; }
|
||||
|
||||
/* Summary */
|
||||
.summary-box {
|
||||
background: #181825;
|
||||
border: 1px solid #313244;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.summary-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 14px 18px;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #313244;
|
||||
}
|
||||
.summary-row:last-child { border-bottom: none; }
|
||||
.summary-key { color: #6c7086; }
|
||||
.summary-val { color: #89b4fa; font-weight: 600; font-size: 12px; max-width: 200px; text-align: right; }
|
||||
|
||||
.warn-box {
|
||||
background: rgba(250,179,135,0.08);
|
||||
border: 1px solid rgba(250,179,135,0.2);
|
||||
border-radius: 6px;
|
||||
padding: 10px 12px;
|
||||
font-size: 12px;
|
||||
color: #fab387;
|
||||
}
|
||||
|
||||
/* Log */
|
||||
#log {
|
||||
background: #11111b;
|
||||
border: 1px solid #313244;
|
||||
border-radius: 6px;
|
||||
padding: 10px 12px;
|
||||
height: 50%;
|
||||
overflow-y: auto;
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.log-ok { color: #a6e3a1; }
|
||||
.log-err { color: #f38ba8; }
|
||||
.log-info { color: #6c7086; }
|
||||
.log-warn { color: #f9e2af; }
|
||||
|
||||
/* Progress */
|
||||
.progress-label {
|
||||
font-size: 12px;
|
||||
color: #6c7086;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.progress-wrap {
|
||||
background: #313244;
|
||||
border-radius: 4px;
|
||||
height: 6px;
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
background: linear-gradient(90deg, #89b4fa, #b4befe);
|
||||
width: 0%;
|
||||
transition: width .35s ease;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
.success-wrap { text-align: center; padding-top: 10px; }
|
||||
.success-check {
|
||||
width: 64px; height: 64px;
|
||||
border-radius: 50%;
|
||||
background: rgba(166,227,161,0.12);
|
||||
border: 2px solid #a6e3a1;
|
||||
margin: 0 auto 16px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 28px;
|
||||
color: #a6e3a1;
|
||||
}
|
||||
.success-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #a6e3a1;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.success-sub {
|
||||
font-size: 13px;
|
||||
color: #6c7086;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.success-hint {
|
||||
margin-top: 14px;
|
||||
background: rgba(137,180,250,0.08);
|
||||
border: 1px solid rgba(137,180,250,0.2);
|
||||
border-radius: 6px;
|
||||
padding: 10px 14px;
|
||||
font-size: 12px;
|
||||
color: #89b4fa;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
position: absolute;
|
||||
left: 220px; right: 0; bottom: 0;
|
||||
height: 60px;
|
||||
border-top: 1px solid #313244;
|
||||
background: #181825;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 24px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 11px 28px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
font-size: 15px;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all .15s;
|
||||
min-width: 110px;
|
||||
}
|
||||
.btn:hover { filter: brightness(1.1); }
|
||||
.btn:disabled { opacity: .35; cursor: not-allowed; }
|
||||
.btn-ghost { background: transparent; color: #6c7086; border: 1px solid #313244; }
|
||||
.btn-primary { background: #89b4fa; color: #1e1e2e; }
|
||||
.btn-success { background: #a6e3a1; color: #1e1e2e; }
|
||||
.btn-close { background: #585b70; color: #cdd6f4; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-logo">
|
||||
<div class="sidebar-logo-title">IT Nexus Agent</div>
|
||||
<div class="sidebar-logo-sub">Setup 1.0.0</div>
|
||||
</div>
|
||||
<div class="nav-item active" id="nav1"><div class="nav-num" id="nn1">1</div> Willkommen</div>
|
||||
<div class="nav-item" id="nav2"><div class="nav-num" id="nn2">2</div> Konfiguration</div>
|
||||
<div class="nav-item" id="nav3"><div class="nav-num" id="nn3">3</div> Zusammenfassung</div>
|
||||
<div class="nav-item" id="nav4"><div class="nav-num" id="nn4">4</div> Installation</div>
|
||||
<div class="nav-item" id="nav5"><div class="nav-num" id="nn5">5</div> Abgeschlossen</div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="main">
|
||||
|
||||
<!-- Step 1 -->
|
||||
<div class="step active" id="step1">
|
||||
<div class="step-title">Willkommen</div>
|
||||
<div class="step-subtitle">Der IT Nexus Agent wird als Windows-Dienst installiert und sendet alle 5 Minuten Systemdaten an das IT Nexus Dashboard.</div>
|
||||
<ul class="feature-list">
|
||||
<li class="feature-item"><span class="feature-dot"></span> CPU, RAM & Festplatten-Auslastung</li>
|
||||
<li class="feature-item"><span class="feature-dot"></span> Installierte Software</li>
|
||||
<li class="feature-item"><span class="feature-dot"></span> Windows Update Status</li>
|
||||
<li class="feature-item"><span class="feature-dot"></span> Angemeldeter Benutzer & Uptime</li>
|
||||
<li class="feature-item"><span class="feature-dot"></span> Netzwerk & Systeminformationen</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="step" id="step2">
|
||||
<div class="step-title">Konfiguration</div>
|
||||
<div class="step-subtitle">Serververbindung konfigurieren.</div>
|
||||
<div class="field">
|
||||
<label>Server URL</label>
|
||||
<input type="text" id="serverUrl" value="https://it-nexus.cereda-systems.de">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Agent API Key</label>
|
||||
<input type="text" id="agentKey" value="cereda-agent-2024-secure-key">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Installationsverzeichnis</label>
|
||||
<input type="text" id="installDir" value="C:\ProgramData\IT Nexus Agent" readonly>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="step" id="step3">
|
||||
<div class="step-title">Bereit zur Installation</div>
|
||||
<div class="step-subtitle">Bitte alles pruefen, dann auf Installieren klicken.</div>
|
||||
<div class="summary-box">
|
||||
<div class="summary-row"><span class="summary-key">Verzeichnis</span><span class="summary-val" id="sum-dir"></span></div>
|
||||
<div class="summary-row"><span class="summary-key">Server</span><span class="summary-val" id="sum-url"></span></div>
|
||||
<div class="summary-row"><span class="summary-key">Scheduled Task</span><span class="summary-val">Alle 5 Minuten (SYSTEM)</span></div>
|
||||
<div class="summary-row"><span class="summary-key">Agent Version</span><span class="summary-val">1.0.0</span></div>
|
||||
</div>
|
||||
<div class="warn-box">Hinweis: Es erscheint eine UAC-Abfrage fuer Administrator-Rechte.</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="step" id="step4">
|
||||
<div class="step-title">Installation</div>
|
||||
<div class="progress-label" id="progLabel">Vorbereitung...</div>
|
||||
<div class="progress-wrap"><div class="progress-fill" id="progBar"></div></div>
|
||||
<div id="log"></div>
|
||||
</div>
|
||||
|
||||
<!-- Step 5 -->
|
||||
<div class="step" id="step5">
|
||||
<div class="success-wrap">
|
||||
<div class="success-check">✓</div>
|
||||
<div class="success-title">Installation abgeschlossen</div>
|
||||
<div class="success-sub">Der IT Nexus Agent ist installiert und aktiv.<br>Er sendet alle 5 Minuten Daten an das Dashboard.</div>
|
||||
<div class="success-hint">Sichtbar unter: IT Nexus → Administration → Agent Monitoring</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="footer">
|
||||
<button class="btn btn-ghost" id="btnBack" onclick="prevStep()" style="display:none">Zurueck</button>
|
||||
<button class="btn btn-ghost" id="btnCancel" onclick="window.close()">Abbrechen</button>
|
||||
<button class="btn btn-primary" id="btnNext" onclick="nextStep()">Weiter</button>
|
||||
</div>
|
||||
|
||||
<script language="JScript">
|
||||
var step = 1;
|
||||
var shell = new ActiveXObject("WScript.Shell");
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
|
||||
// Groesse anhand Bildschirmaufloesung berechnen (60% Breite, 70% Hoehe, min/max begrenzt)
|
||||
var w = Math.min(Math.max(Math.round(screen.availWidth * 0.60), 700), 1100);
|
||||
var h = Math.min(Math.max(Math.round(screen.availHeight * 0.70), 560), 820);
|
||||
window.resizeTo(w, h);
|
||||
window.moveTo((screen.availWidth-w)/2, (screen.availHeight-h)/2);
|
||||
|
||||
// Schriftgroesse skalieren
|
||||
var scale = w / 780;
|
||||
document.body.style.fontSize = Math.round(13 * scale) + "px";
|
||||
|
||||
function updateNav() {
|
||||
for (var i=1;i<=5;i++) {
|
||||
var n = document.getElementById("nav"+i);
|
||||
var nn = document.getElementById("nn"+i);
|
||||
if (i < step) { n.className="nav-item done"; nn.innerHTML="✓"; }
|
||||
else if (i === step) { n.className="nav-item active"; nn.innerHTML=i; }
|
||||
else { n.className="nav-item"; nn.innerHTML=i; }
|
||||
}
|
||||
}
|
||||
|
||||
function showStep(n) {
|
||||
for (var i=1;i<=5;i++) {
|
||||
var el=document.getElementById("step"+i);
|
||||
if(el) el.className=(i===n)?"step active":"step";
|
||||
}
|
||||
step=n;
|
||||
updateNav();
|
||||
|
||||
var btnBack = document.getElementById("btnBack");
|
||||
var btnCancel = document.getElementById("btnCancel");
|
||||
var btnNext = document.getElementById("btnNext");
|
||||
|
||||
btnBack.style.display = (n>1 && n<4) ? "" : "none";
|
||||
btnCancel.style.display = (n>=4) ? "none" : "";
|
||||
|
||||
if (n===3) {
|
||||
document.getElementById("sum-dir").innerText = document.getElementById("installDir").value;
|
||||
document.getElementById("sum-url").innerText = document.getElementById("serverUrl").value;
|
||||
btnNext.className = "btn btn-success";
|
||||
btnNext.innerText = "Installieren";
|
||||
} else if (n===4) {
|
||||
btnNext.style.display="none";
|
||||
startInstall();
|
||||
} else if (n===5) {
|
||||
btnNext.className="btn btn-close";
|
||||
btnNext.innerText="Schliessen";
|
||||
btnNext.style.display="";
|
||||
} else {
|
||||
btnNext.className="btn btn-primary";
|
||||
btnNext.innerText="Weiter";
|
||||
btnNext.style.display="";
|
||||
}
|
||||
}
|
||||
|
||||
function nextStep() { if(step===5){window.close();return;} showStep(step+1); }
|
||||
function prevStep() { if(step>1) showStep(step-1); }
|
||||
|
||||
function log(msg, type) {
|
||||
var el=document.getElementById("log");
|
||||
el.innerHTML+='<div class="'+(type||"log-info")+'">'+msg+'</div>';
|
||||
el.scrollTop=el.scrollHeight;
|
||||
}
|
||||
function setProgress(pct, label) {
|
||||
document.getElementById("progBar").style.width=pct+"%";
|
||||
if(label) document.getElementById("progLabel").innerText=label;
|
||||
}
|
||||
function sleep(ms) { var s=new Date().getTime(); while(new Date().getTime()-s<ms){} }
|
||||
function writeFile(path, content) {
|
||||
var f=fso.CreateTextFile(path,true,false);
|
||||
f.Write(content); f.Close();
|
||||
}
|
||||
|
||||
function startInstall() {
|
||||
try {
|
||||
var installDir = document.getElementById("installDir").value;
|
||||
var serverUrl = document.getElementById("serverUrl").value;
|
||||
var agentKey = document.getElementById("agentKey").value;
|
||||
|
||||
setProgress(10, "Erstelle Verzeichnis...");
|
||||
sleep(300);
|
||||
if (!fso.FolderExists(installDir)) fso.CreateFolder(installDir);
|
||||
log("Verzeichnis erstellt: " + installDir, "log-ok");
|
||||
setProgress(25, "Kopiere Agent-Dateien...");
|
||||
sleep(300);
|
||||
|
||||
var htaDir = fso.GetParentFolderName(location.href.replace("file:///","").replace(/\//g,"\\"));
|
||||
try { fso.CopyFile(htaDir+"\\it-nexus-agent.ps1", installDir+"\\it-nexus-agent.ps1", true); }
|
||||
catch(e) { log("Agent-Script wird neu erstellt...", "log-warn"); }
|
||||
log("Agent-Script kopiert", "log-ok");
|
||||
|
||||
setProgress(40, "Schreibe Konfiguration...");
|
||||
sleep(200);
|
||||
writeFile(installDir+"\\config.json", '{\n "server_url": "'+serverUrl+'",\n "agent_key": "'+agentKey+'"\n}');
|
||||
log("Konfiguration gespeichert", "log-ok");
|
||||
|
||||
setProgress(60, "Registriere Scheduled Task...");
|
||||
sleep(300);
|
||||
|
||||
var ps = [
|
||||
'$d = "'+installDir+'"',
|
||||
'$a = New-ScheduledTaskAction -Execute "powershell.exe" -Argument ("-ExecutionPolicy Bypass -NonInteractive -WindowStyle Hidden -File `\\"$d\\it-nexus-agent.ps1`\\"")',
|
||||
'$t = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 5) -Once -At (Get-Date)',
|
||||
'$s = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2) -MultipleInstances IgnoreNew -StartWhenAvailable',
|
||||
'$p = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest',
|
||||
'Unregister-ScheduledTask -TaskName "IT Nexus Agent" -Confirm:$false -ErrorAction SilentlyContinue',
|
||||
'Register-ScheduledTask -TaskName "IT Nexus Agent" -Action $a -Trigger $t -Settings $s -Principal $p -Force | Out-Null',
|
||||
'Start-ScheduledTask -TaskName "IT Nexus Agent"'
|
||||
].join("\r\n");
|
||||
|
||||
writeFile(installDir+"\\setup-task.ps1", ps);
|
||||
|
||||
// Als Administrator ausfuehren (UAC-Prompt)
|
||||
var shellApp = new ActiveXObject("Shell.Application");
|
||||
shellApp.ShellExecute(
|
||||
"powershell.exe",
|
||||
"-ExecutionPolicy Bypass -File \"" + installDir + "\\setup-task.ps1\"",
|
||||
"",
|
||||
"runas",
|
||||
1
|
||||
);
|
||||
// Warten bis Task registriert ist
|
||||
sleep(4000);
|
||||
|
||||
setProgress(85, "Pruefe Installation...");
|
||||
sleep(600);
|
||||
log("Scheduled Task registriert (alle 5 Minuten)", "log-ok");
|
||||
log("Erster Checkin wird ausgefuehrt...", "log-info");
|
||||
sleep(400);
|
||||
log("Agent ist aktiv!", "log-ok");
|
||||
|
||||
setProgress(100, "Abgeschlossen");
|
||||
sleep(800);
|
||||
showStep(5);
|
||||
|
||||
} catch(e) {
|
||||
log("Fehler: " + e.message, "log-err");
|
||||
setProgress(0, "Fehler aufgetreten");
|
||||
var btn=document.getElementById("btnNext");
|
||||
btn.innerText="Schliessen"; btn.className="btn btn-ghost"; btn.style.display="";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
74
agent/ann-watcher.ps1
Normal file
74
agent/ann-watcher.ps1
Normal file
@@ -0,0 +1,74 @@
|
||||
# IT Nexus Announcement Watcher
|
||||
# Wird alle 15 Sekunden als SYSTEM ausgefuehrt
|
||||
# Zeigt Ankuendigungen als Desktop-Popup fuer den eingeloggten Benutzer
|
||||
|
||||
param()
|
||||
$cfg = Get-Content 'C:\ProgramData\IT Nexus Agent\config.json' -Raw | ConvertFrom-Json
|
||||
$url = $cfg.server_url.TrimEnd('/')
|
||||
$key = $cfg.agent_key
|
||||
|
||||
function Show-AnnDialog($ann) {
|
||||
$id = $ann.id
|
||||
$dlg = "C:\ProgramData\IT Nexus Agent\ann_$id.ps1"
|
||||
if (Test-Path $dlg) { return }
|
||||
|
||||
$title = ($ann.title -replace "'", "''")
|
||||
$message = ($ann.message -replace "'", "''")
|
||||
$accent = switch ($ann.type) { 'warning'{'220,50,50'} 'maintenance'{'245,158,11'} default{'99,102,241'} }
|
||||
$label = switch ($ann.type) { 'warning'{'WICHTIGE WARNUNG'} 'maintenance'{'WARTUNGSANKUENDIGUNG'} default{'INFORMATION'} }
|
||||
$ackUrl = "$url/api/announcements/$id/ack-agent"
|
||||
$n = [System.Environment]::NewLine
|
||||
|
||||
$headerColor = switch ($ann.type) { 'warning'{'220,53,69'} 'maintenance'{'255,140,0'} default{'0,120,212'} }
|
||||
$iconText = switch ($ann.type) { 'warning'{'⚠'} 'maintenance'{'🔧'} default{'ℹ'} }
|
||||
|
||||
$code = "Add-Type -AssemblyName System.Windows.Forms,System.Drawing$n"
|
||||
# Hauptfenster - weißer Hintergrund, professionell
|
||||
$code += "`$f=New-Object System.Windows.Forms.Form;`$f.Text='IT Nexus Mitteilung';`$f.Size=New-Object System.Drawing.Size(480,320);`$f.StartPosition='CenterScreen';`$f.FormBorderStyle='FixedSingle';`$f.MaximizeBox=`$false;`$f.MinimizeBox=`$false;`$f.TopMost=`$true;`$f.BackColor=[System.Drawing.Color]::White$n"
|
||||
# Farbiger Header-Balken
|
||||
$code += "`$hdr=New-Object System.Windows.Forms.Panel;`$hdr.Size=New-Object System.Drawing.Size(480,56);`$hdr.Location=New-Object System.Drawing.Point(0,0);`$hdr.BackColor=[System.Drawing.Color]::FromArgb($headerColor);`$f.Controls.Add(`$hdr)$n"
|
||||
# Logo-Text links im Header
|
||||
$code += "`$logo=New-Object System.Windows.Forms.Label;`$logo.Text='IT Nexus';`$logo.Font=New-Object System.Drawing.Font('Segoe UI',11,[System.Drawing.FontStyle]::Bold);`$logo.ForeColor=[System.Drawing.Color]::White;`$logo.Location=New-Object System.Drawing.Point(16,8);`$logo.Size=New-Object System.Drawing.Size(120,20);`$hdr.Controls.Add(`$logo)$n"
|
||||
# Typ-Label im Header
|
||||
$code += "`$lbl=New-Object System.Windows.Forms.Label;`$lbl.Text='$label';`$lbl.Font=New-Object System.Drawing.Font('Segoe UI',8);`$lbl.ForeColor=[System.Drawing.Color]::FromArgb(220,240,255);`$lbl.Location=New-Object System.Drawing.Point(16,30);`$lbl.Size=New-Object System.Drawing.Size(420,18);`$hdr.Controls.Add(`$lbl)$n"
|
||||
# Titel
|
||||
$code += "`$lt=New-Object System.Windows.Forms.Label;`$lt.Text='$title';`$lt.Font=New-Object System.Drawing.Font('Segoe UI',12,[System.Drawing.FontStyle]::Bold);`$lt.ForeColor=[System.Drawing.Color]::FromArgb(30,30,30);`$lt.Location=New-Object System.Drawing.Point(16,72);`$lt.Size=New-Object System.Drawing.Size(444,28);`$f.Controls.Add(`$lt)$n"
|
||||
# Trennlinie
|
||||
$code += "`$sep=New-Object System.Windows.Forms.Panel;`$sep.Size=New-Object System.Drawing.Size(448,1);`$sep.Location=New-Object System.Drawing.Point(16,104);`$sep.BackColor=[System.Drawing.Color]::FromArgb(220,220,220);`$f.Controls.Add(`$sep)$n"
|
||||
# Nachricht
|
||||
$code += "`$lm=New-Object System.Windows.Forms.Label;`$lm.Text='$message';`$lm.Font=New-Object System.Drawing.Font('Segoe UI',10);`$lm.ForeColor=[System.Drawing.Color]::FromArgb(60,60,60);`$lm.Location=New-Object System.Drawing.Point(16,112);`$lm.Size=New-Object System.Drawing.Size(444,120);`$lm.AutoSize=`$false;`$f.Controls.Add(`$lm)$n"
|
||||
# Button
|
||||
$code += "`$btn=New-Object System.Windows.Forms.Button;`$btn.Text='✓ Gelesen und bestätigt';`$btn.Font=New-Object System.Drawing.Font('Segoe UI',10,[System.Drawing.FontStyle]::Bold);`$btn.ForeColor=[System.Drawing.Color]::White;`$btn.BackColor=[System.Drawing.Color]::FromArgb($headerColor);`$btn.FlatStyle='Flat';`$btn.FlatAppearance.BorderSize=0;`$btn.Location=New-Object System.Drawing.Point(16,244);`$btn.Size=New-Object System.Drawing.Size(444,36);`$btn.DialogResult=[System.Windows.Forms.DialogResult]::OK;`$f.Controls.Add(`$btn);`$f.AcceptButton=`$btn$n"
|
||||
$code += "if(`$f.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){$n"
|
||||
$code += " `$b=[System.Text.Encoding]::UTF8.GetBytes('{""hostname"":""+`$env:COMPUTERNAME+'""}')$n"
|
||||
$code += " `$r=[System.Net.WebRequest]::Create('$ackUrl')$n"
|
||||
$code += " `$r.Method='POST';`$r.ContentType='application/json';`$r.Headers.Add('X-Agent-Key','$key');`$r.ContentLength=`$b.Length$n"
|
||||
$code += " `$s=`$r.GetRequestStream();`$s.Write(`$b,0,`$b.Length);`$s.Close()$n"
|
||||
$code += " try{`$r.GetResponse().Close()}catch{}$n"
|
||||
$code += " Remove-Item '$dlg' -Force -ErrorAction SilentlyContinue$n"
|
||||
$code += "}$n"
|
||||
|
||||
$code | Out-File -FilePath $dlg -Encoding UTF8 -Force
|
||||
|
||||
$loggedUser = (Get-CimInstance Win32_ComputerSystem).UserName
|
||||
if ($loggedUser) {
|
||||
$tn = "ITNexus-AnnDlg-$id"
|
||||
Unregister-ScheduledTask -TaskName $tn -Confirm:$false -ErrorAction SilentlyContinue
|
||||
$a = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$dlg`""
|
||||
$t = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(2)
|
||||
$p = New-ScheduledTaskPrincipal -UserId $loggedUser -LogonType Interactive -RunLevel Limited
|
||||
$s = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 60) -StartWhenAvailable
|
||||
Register-ScheduledTask -TaskName $tn -Action $a -Trigger $t -Principal $p -Settings $s -Force | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$body = [System.Text.Encoding]::UTF8.GetBytes('{"hostname":"'+$env:COMPUTERNAME+'"}')
|
||||
$req = [System.Net.WebRequest]::Create("$url/api/monitoring/announcements-poll")
|
||||
$req.Method = 'POST'; $req.ContentType = 'application/json'
|
||||
$req.Headers.Add('X-Agent-Key', $key); $req.ContentLength = $body.Length
|
||||
$st = $req.GetRequestStream(); $st.Write($body, 0, $body.Length); $st.Close()
|
||||
$rd = New-Object System.IO.StreamReader($req.GetResponse().GetResponseStream())
|
||||
$data = $rd.ReadToEnd() | ConvertFrom-Json
|
||||
if ($data.announcements) { foreach ($a in $data.announcements) { Show-AnnDialog $a } }
|
||||
} catch {}
|
||||
4
agent/config.example.json
Normal file
4
agent/config.example.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"server_url": "https://it-nexus.cereda-systems.de",
|
||||
"agent_key": "DEIN-AGENT-KEY-HIER"
|
||||
}
|
||||
4
agent/config.json.template
Normal file
4
agent/config.json.template
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"server_url": "https://it-nexus.cereda-systems.de",
|
||||
"agent_key": "cereda-agent-2024-secure-key"
|
||||
}
|
||||
44
agent/install.ps1
Normal file
44
agent/install.ps1
Normal file
@@ -0,0 +1,44 @@
|
||||
# IT Nexus Agent - Installer
|
||||
# Cereda Systems GmbH
|
||||
|
||||
$InstallDir = "$env:ProgramData\IT Nexus Agent"
|
||||
$AgentKey = "cereda-agent-2024-secure-key"
|
||||
$ServerUrl = "https://it-nexus.cereda-systems.de"
|
||||
$TaskName = "IT Nexus Agent"
|
||||
|
||||
Write-Host "=== IT Nexus Agent Installation ===" -ForegroundColor Cyan
|
||||
|
||||
# Verzeichnis erstellen
|
||||
if (-not (Test-Path $InstallDir)) {
|
||||
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Dateien kopieren
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
Copy-Item "$ScriptDir\it-nexus-agent.ps1" "$InstallDir\it-nexus-agent.ps1" -Force
|
||||
|
||||
# Config schreiben
|
||||
$config = @{ server_url = $ServerUrl; agent_key = $AgentKey } | ConvertTo-Json
|
||||
Set-Content -Path "$InstallDir\config.json" -Value $config -Force
|
||||
|
||||
# Alten Task entfernen falls vorhanden
|
||||
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
|
||||
|
||||
# Scheduled Task erstellen (laeuft alle 5 Minuten als SYSTEM)
|
||||
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -NonInteractive -WindowStyle Hidden -File `"$InstallDir\it-nexus-agent.ps1`""
|
||||
$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 5) -Once -At (Get-Date)
|
||||
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2) -MultipleInstances IgnoreNew -StartWhenAvailable
|
||||
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest -ErrorAction SilentlyContinue
|
||||
if (-not $principal) {
|
||||
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -RunLevel Highest
|
||||
}
|
||||
|
||||
Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Force | Out-Null
|
||||
|
||||
Write-Host "Installiert in: $InstallDir" -ForegroundColor Green
|
||||
Write-Host "Scheduled Task '$TaskName' erstellt (alle 5 Min)" -ForegroundColor Green
|
||||
Write-Host "Server: $ServerUrl" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Erster Checkin wird jetzt ausgefuehrt..." -ForegroundColor Yellow
|
||||
Start-ScheduledTask -TaskName $TaskName
|
||||
Write-Host "Fertig!" -ForegroundColor Green
|
||||
606
agent/it-nexus-agent.ps1
Normal file
606
agent/it-nexus-agent.ps1
Normal file
@@ -0,0 +1,606 @@
|
||||
# IT Nexus Monitoring Agent v1.3
|
||||
# Cereda Systems GmbH
|
||||
# Laedt Systemdaten und sendet sie an IT Nexus
|
||||
|
||||
$AgentVersion = "1.3.1"
|
||||
$ConfigPath = Join-Path $PSScriptRoot "config.json"
|
||||
$LogPath = Join-Path $PSScriptRoot "agent.log"
|
||||
|
||||
function Write-Log($msg) {
|
||||
$line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $msg"
|
||||
Add-Content -Path $LogPath -Value $line -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# Config laden
|
||||
if (-not (Test-Path $ConfigPath)) {
|
||||
Write-Log "ERROR: config.json nicht gefunden"
|
||||
exit 1
|
||||
}
|
||||
$config = Get-Content $ConfigPath | ConvertFrom-Json
|
||||
$ServerUrl = $config.server_url.TrimEnd('/')
|
||||
$AgentKey = $config.agent_key
|
||||
|
||||
function Get-CpuUsage {
|
||||
try {
|
||||
$pc = [System.Diagnostics.PerformanceCounter]::new("Processor", "% Processor Time", "_Total")
|
||||
$pc.NextValue() | Out-Null
|
||||
Start-Sleep -Milliseconds 800
|
||||
return [math]::Round($pc.NextValue(), 1)
|
||||
} catch { return $null }
|
||||
}
|
||||
|
||||
function Get-RamInfo {
|
||||
try {
|
||||
$os = Get-CimInstance Win32_OperatingSystem
|
||||
$total = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
|
||||
$free = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
|
||||
return @{ total = $total; used = [math]::Round($total - $free, 2) }
|
||||
} catch { return @{ total = $null; used = $null } }
|
||||
}
|
||||
|
||||
function Get-DiskInfo {
|
||||
try {
|
||||
$disk = Get-PSDrive C
|
||||
$total = [math]::Round(($disk.Used + $disk.Free) / 1GB, 2)
|
||||
$free = [math]::Round($disk.Free / 1GB, 2)
|
||||
return @{ total = $total; free = $free }
|
||||
} catch { return @{ total = $null; free = $null } }
|
||||
}
|
||||
|
||||
function Get-CpuInfo {
|
||||
try {
|
||||
$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1
|
||||
return @{ model = $cpu.Name.Trim(); cores = $cpu.NumberOfCores }
|
||||
} catch { return @{ model = $null; cores = $null } }
|
||||
}
|
||||
|
||||
function Get-MacAddress {
|
||||
try {
|
||||
$mac = (Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled } | Select-Object -First 1).MACAddress
|
||||
return $mac
|
||||
} catch { return $null }
|
||||
}
|
||||
|
||||
function Get-InstalledSoftware {
|
||||
try {
|
||||
$paths = @(
|
||||
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
|
||||
'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
|
||||
)
|
||||
$apps = Get-ItemProperty $paths -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.DisplayName -and $_.DisplayName -notmatch '^KB\d+' } |
|
||||
Select-Object -ExpandProperty DisplayName -Unique |
|
||||
ForEach-Object { [System.Text.RegularExpressions.Regex]::Replace($_, '[^\x20-\x7E]', '') } |
|
||||
Where-Object { $_.Length -gt 2 } |
|
||||
Sort-Object |
|
||||
Select-Object -First 100
|
||||
return $apps
|
||||
} catch { return @() }
|
||||
}
|
||||
|
||||
function Get-PendingUpdates {
|
||||
try {
|
||||
$session = New-Object -ComObject Microsoft.Update.Session
|
||||
$searcher = $session.CreateUpdateSearcher()
|
||||
$result = $searcher.Search("IsInstalled=0 and Type='Software'")
|
||||
return $result.Updates.Count
|
||||
} catch { return 0 }
|
||||
}
|
||||
|
||||
function Get-UptimeHours {
|
||||
try {
|
||||
$uptime = (Get-Date) - (gcim Win32_OperatingSystem).LastBootUpTime
|
||||
return [math]::Round($uptime.TotalHours, 1)
|
||||
} catch { return $null }
|
||||
}
|
||||
|
||||
function Get-LastUser {
|
||||
try {
|
||||
$user = (Get-CimInstance Win32_ComputerSystem).UserName
|
||||
if ($user) { return $user.Split('\')[-1] }
|
||||
$profile = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*' |
|
||||
Where-Object { $_.ProfileImagePath -like 'C:\Users\*' -and $_.ProfileImagePath -notlike '*default*' } |
|
||||
Sort-Object { $_.PSChildName } | Select-Object -Last 1
|
||||
return ($profile.ProfileImagePath -split '\\')[-1]
|
||||
} catch { return $null }
|
||||
}
|
||||
|
||||
function Get-TpmInfo {
|
||||
try {
|
||||
$tpm = Get-WmiObject -Namespace "Root\CIMv2\Security\MicrosoftTpm" -Class Win32_Tpm -ErrorAction Stop
|
||||
if ($tpm) {
|
||||
$specVer = $tpm.SpecVersion
|
||||
$isV2 = $specVer -like "*2.0*"
|
||||
return @{ present = $true; version = $specVer; is_v2 = $isV2 }
|
||||
}
|
||||
return @{ present = $false; version = $null; is_v2 = $false }
|
||||
} catch {
|
||||
return @{ present = $false; version = $null; is_v2 = $false }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-SecureBootStatus {
|
||||
try {
|
||||
$sb = Confirm-SecureBootUEFI -ErrorAction Stop
|
||||
return [bool]$sb
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Get-Win11Readiness {
|
||||
$tpm = Get-TpmInfo
|
||||
$sb = Get-SecureBootStatus
|
||||
$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1
|
||||
$ram = (Get-CimInstance Win32_OperatingSystem).TotalVisibleMemorySize / 1MB
|
||||
|
||||
$cpuOk = $cpu -and $cpu.NumberOfCores -ge 2 -and $cpu.MaxClockSpeed -ge 1000
|
||||
$ramOk = $ram -ge 4
|
||||
$ready = $tpm.is_v2 -and $sb -and $cpuOk -and $ramOk
|
||||
|
||||
return @{
|
||||
tpm_present = $tpm.present
|
||||
tpm_version = if ($tpm.version) { $tpm.version } else { $null }
|
||||
tpm_v2 = $tpm.is_v2
|
||||
secure_boot = $sb
|
||||
win11_ready = $ready
|
||||
}
|
||||
}
|
||||
|
||||
# Systemdaten sammeln
|
||||
Write-Log "Sammle Systemdaten..."
|
||||
|
||||
$cpu = Get-CpuInfo
|
||||
$ram = Get-RamInfo
|
||||
$disk = Get-DiskInfo
|
||||
$cpuPct = Get-CpuUsage
|
||||
$mac = Get-MacAddress
|
||||
$updates = Get-PendingUpdates
|
||||
$uptime = Get-UptimeHours
|
||||
$lastUser = Get-LastUser
|
||||
$software = Get-InstalledSoftware
|
||||
$win11 = Get-Win11Readiness
|
||||
|
||||
$ip = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {
|
||||
$_.InterfaceAlias -notlike '*Loopback*' -and
|
||||
$_.InterfaceAlias -notlike '*vEthernet*' -and
|
||||
$_.InterfaceAlias -notlike '*WSL*' -and
|
||||
$_.InterfaceAlias -notlike '*Virtual*' -and
|
||||
$_.IPAddress -notlike '169.*' -and
|
||||
$_.IPAddress -notlike '172.*'
|
||||
} | Select-Object -First 1).IPAddress
|
||||
if (-not $ip) {
|
||||
$ip = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {
|
||||
$_.InterfaceAlias -notlike '*Loopback*' -and
|
||||
$_.InterfaceAlias -notlike '*vEthernet*' -and
|
||||
$_.IPAddress -notlike '169.*'
|
||||
} | Select-Object -First 1).IPAddress
|
||||
}
|
||||
$os = Get-CimInstance Win32_OperatingSystem
|
||||
$domain = $env:USERDOMAIN
|
||||
|
||||
$payload = @{
|
||||
hostname = $env:COMPUTERNAME
|
||||
ip_address = $ip
|
||||
mac_address = $mac
|
||||
os_name = $os.Caption
|
||||
os_version = $os.Version
|
||||
cpu_model = $cpu.model
|
||||
cpu_cores = $cpu.cores
|
||||
cpu_usage_percent = $cpuPct
|
||||
ram_total_gb = $ram.total
|
||||
ram_used_gb = $ram.used
|
||||
disk_total_gb = $disk.total
|
||||
disk_free_gb = $disk.free
|
||||
last_user = $lastUser
|
||||
uptime_hours = $uptime
|
||||
domain = $domain
|
||||
agent_version = $AgentVersion
|
||||
installed_software = $software
|
||||
windows_updates_pending = $updates
|
||||
tpm_present = $win11.tpm_present
|
||||
tpm_version = $win11.tpm_version
|
||||
tpm_v2 = $win11.tpm_v2
|
||||
secure_boot = $win11.secure_boot
|
||||
win11_ready = $win11.win11_ready
|
||||
} | ConvertTo-Json -Depth 3
|
||||
|
||||
# --- An IT Nexus senden ---
|
||||
function Invoke-PatchCommand($cmd, $cmdId) {
|
||||
Write-Log "PATCH: Command empfangen: $($cmd) (ID: $cmdId)"
|
||||
$result = "OK"
|
||||
try {
|
||||
switch ($cmd) {
|
||||
'check_updates' {
|
||||
UsoClient.exe StartScan 2>$null
|
||||
Start-Sleep -Seconds 5
|
||||
$result = "Update-Scan gestartet"
|
||||
Write-Log "PATCH: Update-Scan gestartet"
|
||||
}
|
||||
'install_updates' {
|
||||
UsoClient.exe StartDownload 2>$null
|
||||
Start-Sleep -Seconds 3
|
||||
UsoClient.exe StartInstall 2>$null
|
||||
$result = "Update-Installation gestartet"
|
||||
Write-Log "PATCH: Update-Installation gestartet"
|
||||
}
|
||||
'update_agent' {
|
||||
Write-Log "UPDATE: Manuelles Agent-Update angefordert..."
|
||||
try {
|
||||
$scriptPath = $MyInvocation.MyCommand.Path
|
||||
$tempPath = "$scriptPath.update"
|
||||
$updateHeaders = @{ 'X-Agent-Key' = $AgentKey }
|
||||
Invoke-WebRequest -Uri "$ServerUrl/api/monitoring/agent-script" `
|
||||
-Headers $updateHeaders -OutFile $tempPath -TimeoutSec 30
|
||||
if ((Get-Item $tempPath -ErrorAction SilentlyContinue).Length -gt 1024) {
|
||||
Copy-Item -Path $tempPath -Destination $scriptPath -Force
|
||||
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
|
||||
$result = "Agent erfolgreich aktualisiert - neue Version aktiv ab naechstem Run"
|
||||
Write-Log "UPDATE: Manuelles Update erfolgreich"
|
||||
} else {
|
||||
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
|
||||
$result = "Fehler: Heruntergeladene Datei ungueltig"
|
||||
Write-Log "UPDATE ERROR: Datei zu klein"
|
||||
}
|
||||
} catch {
|
||||
$result = "Fehler: $($_.Exception.Message)"
|
||||
Write-Log "UPDATE ERROR: $result"
|
||||
}
|
||||
}
|
||||
'upgrade_win11' {
|
||||
Write-Log "WIN11: Starte Windows 11 Upgrade-Prozess..."
|
||||
$assistantPath = "C:\ProgramData\IT Nexus Agent\Win11Upgrade.exe"
|
||||
try {
|
||||
Write-Log "WIN11: Lade Installation Assistant herunter..."
|
||||
Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=2171764" -OutFile $assistantPath -TimeoutSec 300
|
||||
if ((Get-Item $assistantPath -ErrorAction SilentlyContinue).Length -gt 1MB) {
|
||||
# Als angemeldeter Benutzer ausfuehren damit UI sichtbar ist
|
||||
$loggedInUser = (Get-CimInstance Win32_ComputerSystem).UserName
|
||||
if ($loggedInUser -and $loggedInUser -ne '') {
|
||||
Unregister-ScheduledTask -TaskName "IT Nexus Win11 Upgrade" -Confirm:$false -ErrorAction SilentlyContinue
|
||||
$action = New-ScheduledTaskAction -Execute $assistantPath -Argument "/skipeula /auto upgrade"
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(20)
|
||||
$principal = New-ScheduledTaskPrincipal -UserId $loggedInUser -LogonType Interactive -RunLevel Highest
|
||||
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 3)
|
||||
Register-ScheduledTask -TaskName "IT Nexus Win11 Upgrade" -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null
|
||||
Start-ScheduledTask -TaskName "IT Nexus Win11 Upgrade"
|
||||
$reportBody = @{ command_id = $cmdId; status = 'running'; result = "Windows 11 Upgrade gestartet fuer Benutzer $loggedInUser - Fortschritt sichtbar auf dem Geraet" } | ConvertTo-Json
|
||||
Invoke-RestMethod -Uri "$ServerUrl/api/patch/commands/result" -Method POST -Body $reportBody -Headers @{ 'Content-Type' = 'application/json'; 'X-Agent-Key' = $AgentKey } -TimeoutSec 10 -ErrorAction SilentlyContinue
|
||||
Write-Log "WIN11: Upgrade als $loggedInUser gestartet (Status: running)"
|
||||
return
|
||||
} else {
|
||||
Start-Process -FilePath $assistantPath -ArgumentList "/quietinstall /skipeula /auto upgrade" -NoNewWindow
|
||||
$reportBody = @{ command_id = $cmdId; status = 'running'; result = "Windows 11 Upgrade gestartet (kein Benutzer angemeldet)" } | ConvertTo-Json
|
||||
Invoke-RestMethod -Uri "$ServerUrl/api/patch/commands/result" -Method POST -Body $reportBody -Headers @{ 'Content-Type' = 'application/json'; 'X-Agent-Key' = $AgentKey } -TimeoutSec 10 -ErrorAction SilentlyContinue
|
||||
Write-Log "WIN11: Upgrade als SYSTEM gestartet (kein User)"
|
||||
return
|
||||
}
|
||||
} else {
|
||||
$result = "Fehler: Download fehlgeschlagen oder Datei zu klein"
|
||||
Write-Log "WIN11 ERROR: Download fehlgeschlagen"
|
||||
}
|
||||
} catch {
|
||||
$result = "Fehler: $($_.Exception.Message)"
|
||||
Write-Log "WIN11 ERROR: $result"
|
||||
}
|
||||
}
|
||||
'reboot' {
|
||||
$result = "Neustart wird in 60 Sekunden durchgefuehrt"
|
||||
Write-Log "PATCH: Neustart geplant"
|
||||
$reportBody = @{ command_id = $cmdId; status = 'done'; result = $result } | ConvertTo-Json
|
||||
Invoke-RestMethod -Uri "$ServerUrl/api/patch/commands/result" `
|
||||
-Method POST -Body $reportBody `
|
||||
-Headers @{ 'Content-Type' = 'application/json'; 'X-Agent-Key' = $AgentKey } `
|
||||
-TimeoutSec 10 -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 5
|
||||
shutdown.exe /r /t 60 /c "IT Nexus Patch Management - Geplanter Neustart"
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
$result = "Fehler: $($_.Exception.Message)"
|
||||
Write-Log "PATCH ERROR: $result"
|
||||
}
|
||||
|
||||
try {
|
||||
$reportBody = @{ command_id = $cmdId; status = 'done'; result = $result } | ConvertTo-Json
|
||||
Invoke-RestMethod -Uri "$ServerUrl/api/patch/commands/result" `
|
||||
-Method POST -Body $reportBody `
|
||||
-Headers @{ 'Content-Type' = 'application/json'; 'X-Agent-Key' = $AgentKey } `
|
||||
-TimeoutSec 10
|
||||
} catch {
|
||||
Write-Log "PATCH: Ergebnis-Meldung fehlgeschlagen: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$headers = @{
|
||||
'Content-Type' = 'application/json'
|
||||
'X-Agent-Key' = $AgentKey
|
||||
}
|
||||
$cleanPayload = $payload -replace '[\x00-\x1F\x7F]', ''
|
||||
$response = Invoke-RestMethod -Uri "$ServerUrl/api/monitoring/checkin" `
|
||||
-Method POST -Body $cleanPayload -Headers $headers -TimeoutSec 30
|
||||
Write-Log "OK: Checkin erfolgreich (Hostname: $env:COMPUTERNAME)"
|
||||
|
||||
# Self-Update pruefen
|
||||
$serverVersion = $response.agent_version
|
||||
if ($serverVersion -and $serverVersion -ne $AgentVersion) {
|
||||
Write-Log "UPDATE: Neue Agent-Version verfuegbar: $serverVersion (aktuell: $AgentVersion)"
|
||||
try {
|
||||
$scriptPath = $MyInvocation.MyCommand.Path
|
||||
$tempPath = "$scriptPath.update"
|
||||
$updateHeaders = @{ 'X-Agent-Key' = $AgentKey }
|
||||
Invoke-WebRequest -Uri "$ServerUrl/api/monitoring/agent-script" `
|
||||
-Headers $updateHeaders -OutFile $tempPath -TimeoutSec 30
|
||||
if ((Get-Item $tempPath).Length -gt 1024) {
|
||||
Copy-Item -Path $tempPath -Destination $scriptPath -Force
|
||||
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
|
||||
Write-Log "UPDATE: Agent erfolgreich auf Version $serverVersion aktualisiert."
|
||||
} else {
|
||||
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
|
||||
Write-Log "UPDATE: Heruntergeladene Datei zu klein - Update abgebrochen"
|
||||
}
|
||||
} catch {
|
||||
Write-Log "UPDATE ERROR: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# Laufende Commands pruefen (z.B. Win11 Upgrade)
|
||||
if ($response.running_commands -and $response.running_commands.Count -gt 0) {
|
||||
foreach ($rc in $response.running_commands) {
|
||||
if ($rc.command -eq 'upgrade_win11') {
|
||||
$task = Get-ScheduledTask -TaskName "IT Nexus Win11 Upgrade" -ErrorAction SilentlyContinue
|
||||
$proc = Get-Process -Name "Win11Upgrade" -ErrorAction SilentlyContinue
|
||||
$stillRunning = ($task -and $task.State -eq 'Running') -or ($proc -ne $null)
|
||||
if (-not $stillRunning) {
|
||||
$taskInfo = Get-ScheduledTaskInfo -TaskName "IT Nexus Win11 Upgrade" -ErrorAction SilentlyContinue
|
||||
$exitCode = if ($taskInfo) { $taskInfo.LastTaskResult } else { 0 }
|
||||
$doneResult = if ($exitCode -eq 0) { "Windows 11 Upgrade abgeschlossen" } else { "Upgrade beendet (Code: $exitCode)" }
|
||||
$rb = @{ command_id = $rc.id; status = 'done'; result = $doneResult } | ConvertTo-Json
|
||||
Invoke-RestMethod -Uri "$ServerUrl/api/patch/commands/result" -Method POST -Body $rb -Headers @{ 'Content-Type' = 'application/json'; 'X-Agent-Key' = $AgentKey } -TimeoutSec 10 -ErrorAction SilentlyContinue
|
||||
Write-Log "WIN11: Upgrade abgeschlossen (Code: $exitCode)"
|
||||
} else {
|
||||
Write-Log "WIN11: Upgrade laeuft noch..."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Ankuendigungen anzeigen (als eingeloggter Benutzer via ScheduledTask)
|
||||
if ($response.announcements -and $response.announcements.Count -gt 0) {
|
||||
foreach ($ann in $response.announcements) {
|
||||
try {
|
||||
$annId = $ann.id
|
||||
$annTitle = $ann.title -replace "'", "''"
|
||||
$annMessage = $ann.message -replace "'", "''"
|
||||
$typeLabel = switch ($ann.type) {
|
||||
'warning' { 'WICHTIGE WARNUNG' }
|
||||
'maintenance' { 'WARTUNGSANKUENDIGUNG' }
|
||||
default { 'INFORMATION' }
|
||||
}
|
||||
$accentColor = switch ($ann.type) {
|
||||
'warning' { '220, 50, 50' }
|
||||
'maintenance' { '245, 158, 11' }
|
||||
default { '99, 102, 241' }
|
||||
}
|
||||
|
||||
# PS-Script das im Benutzer-Kontext laeuft und den Dialog zeigt
|
||||
$dialogScript = @"
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
`$form = New-Object System.Windows.Forms.Form
|
||||
`$form.Text = 'IT Nexus - $typeLabel'
|
||||
`$form.Size = New-Object System.Drawing.Size(520, 330)
|
||||
`$form.StartPosition = 'CenterScreen'
|
||||
`$form.FormBorderStyle = 'FixedDialog'
|
||||
`$form.MaximizeBox = `$false
|
||||
`$form.MinimizeBox = `$false
|
||||
`$form.TopMost = `$true
|
||||
`$form.BackColor = [System.Drawing.Color]::FromArgb(24, 24, 37)
|
||||
`$lTitle = New-Object System.Windows.Forms.Label
|
||||
`$lTitle.Text = '$annTitle'
|
||||
`$lTitle.Font = New-Object System.Drawing.Font('Segoe UI', 13, [System.Drawing.FontStyle]::Bold)
|
||||
`$lTitle.ForeColor = [System.Drawing.Color]::White
|
||||
`$lTitle.Location = New-Object System.Drawing.Point(20, 20)
|
||||
`$lTitle.Size = New-Object System.Drawing.Size(460, 36)
|
||||
`$form.Controls.Add(`$lTitle)
|
||||
`$lMsg = New-Object System.Windows.Forms.Label
|
||||
`$lMsg.Text = '$annMessage'
|
||||
`$lMsg.Font = New-Object System.Drawing.Font('Segoe UI', 10)
|
||||
`$lMsg.ForeColor = [System.Drawing.Color]::FromArgb(200, 200, 220)
|
||||
`$lMsg.Location = New-Object System.Drawing.Point(20, 66)
|
||||
`$lMsg.Size = New-Object System.Drawing.Size(460, 155)
|
||||
`$lMsg.AutoSize = `$false
|
||||
`$form.Controls.Add(`$lMsg)
|
||||
`$lHint = New-Object System.Windows.Forms.Label
|
||||
`$lHint.Text = 'Bitte lesen und Kenntnisnahme bestaetigen.'
|
||||
`$lHint.Font = New-Object System.Drawing.Font('Segoe UI', 8, [System.Drawing.FontStyle]::Italic)
|
||||
`$lHint.ForeColor = [System.Drawing.Color]::FromArgb(130, 130, 150)
|
||||
`$lHint.Location = New-Object System.Drawing.Point(20, 228)
|
||||
`$lHint.Size = New-Object System.Drawing.Size(460, 20)
|
||||
`$form.Controls.Add(`$lHint)
|
||||
`$btn = New-Object System.Windows.Forms.Button
|
||||
`$btn.Text = 'Gelesen und bestaetigt'
|
||||
`$btn.Font = New-Object System.Drawing.Font('Segoe UI', 10, [System.Drawing.FontStyle]::Bold)
|
||||
`$btn.ForeColor = [System.Drawing.Color]::White
|
||||
`$btn.BackColor = [System.Drawing.Color]::FromArgb($accentColor)
|
||||
`$btn.FlatStyle = 'Flat'
|
||||
`$btn.Location = New-Object System.Drawing.Point(20, 255)
|
||||
`$btn.Size = New-Object System.Drawing.Size(460, 40)
|
||||
`$btn.DialogResult = [System.Windows.Forms.DialogResult]::OK
|
||||
`$form.Controls.Add(`$btn)
|
||||
`$form.AcceptButton = `$btn
|
||||
`$r = `$form.ShowDialog()
|
||||
if (`$r -eq [System.Windows.Forms.DialogResult]::OK) {
|
||||
`$b = [System.Text.Encoding]::UTF8.GetBytes('{"hostname":"' + `$env:COMPUTERNAME + '"}')
|
||||
`$req = [System.Net.WebRequest]::Create('$ServerUrl/api/announcements/$annId/ack-agent')
|
||||
`$req.Method = 'POST'
|
||||
`$req.ContentType = 'application/json'
|
||||
`$req.Headers.Add('X-Agent-Key','$AgentKey')
|
||||
`$req.ContentLength = `$b.Length
|
||||
`$s = `$req.GetRequestStream(); `$s.Write(`$b,0,`$b.Length); `$s.Close()
|
||||
try { `$req.GetResponse().Close() } catch {}
|
||||
}
|
||||
"@
|
||||
# Dialog-Script temporaer speichern
|
||||
$scriptFile = "C:\ProgramData\IT Nexus Agent\ann_$annId.ps1"
|
||||
$dialogScript | Out-File -FilePath $scriptFile -Encoding UTF8 -Force
|
||||
|
||||
# Eingeloggten Benutzer ermitteln
|
||||
$loggedUser = (Get-CimInstance Win32_ComputerSystem).UserName
|
||||
if ($loggedUser -and $loggedUser -ne '') {
|
||||
$taskName = "ITNexus-Ann-$annId"
|
||||
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
|
||||
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-ExecutionPolicy Bypass -WindowStyle Normal -File `"$scriptFile`""
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(3)
|
||||
$principal = New-ScheduledTaskPrincipal -UserId $loggedUser -LogonType Interactive -RunLevel Limited
|
||||
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 60) -StartWhenAvailable
|
||||
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null
|
||||
Write-Log "ANNOUNCEMENT: Dialog fuer Benutzer $loggedUser gestartet - ID $annId"
|
||||
} else {
|
||||
Write-Log "ANNOUNCEMENT: Kein Benutzer eingeloggt - Dialog wird beim naechsten Check-in versucht"
|
||||
}
|
||||
} catch {
|
||||
Write-Log "ANNOUNCEMENT ERROR: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Pending Patch-Commands verarbeiten
|
||||
if ($response.commands -and $response.commands.Count -gt 0) {
|
||||
Write-Log "PATCH: $($response.commands.Count) Command(s) empfangen"
|
||||
foreach ($cmd in $response.commands) {
|
||||
Invoke-PatchCommand -cmd $cmd.command -cmdId $cmd.id
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.Value__
|
||||
Write-Log "ERROR: Checkin fehlgeschlagen - HTTP $statusCode - $($_.Exception.Message)"
|
||||
try {
|
||||
$reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
|
||||
Write-Log "ERROR Detail: $($reader.ReadToEnd())"
|
||||
} catch {}
|
||||
}
|
||||
|
||||
# ── Schneller Announcement-Poll (alle 15 Sekunden im Hintergrund) ─────────────
|
||||
function Invoke-AnnouncementPoll {
|
||||
try {
|
||||
$pollBody = @{ hostname = $env:COMPUTERNAME } | ConvertTo-Json
|
||||
$pollResp = Invoke-RestMethod -Uri "$ServerUrl/api/monitoring/announcements-poll" `
|
||||
-Method POST -Body $pollBody `
|
||||
-Headers @{ 'Content-Type' = 'application/json'; 'X-Agent-Key' = $AgentKey } `
|
||||
-TimeoutSec 10
|
||||
if ($pollResp.announcements -and $pollResp.announcements.Count -gt 0) {
|
||||
foreach ($ann in $pollResp.announcements) {
|
||||
$annId = $ann.id
|
||||
$annTitle = $ann.title -replace "'", "''"
|
||||
$annMessage = $ann.message -replace "'", "''"
|
||||
$accentColor = switch ($ann.type) {
|
||||
'warning' { '220, 50, 50' }
|
||||
'maintenance' { '245, 158, 11' }
|
||||
default { '99, 102, 241' }
|
||||
}
|
||||
$typeLabel = switch ($ann.type) {
|
||||
'warning' { 'WICHTIGE WARNUNG' }
|
||||
'maintenance' { 'WARTUNGSANKUENDIGUNG' }
|
||||
default { 'INFORMATION' }
|
||||
}
|
||||
$dialogScript = @"
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
`$form = New-Object System.Windows.Forms.Form
|
||||
`$form.Text = 'IT Nexus - $typeLabel'
|
||||
`$form.Size = New-Object System.Drawing.Size(520, 330)
|
||||
`$form.StartPosition = 'CenterScreen'
|
||||
`$form.FormBorderStyle = 'FixedDialog'
|
||||
`$form.MaximizeBox = `$false
|
||||
`$form.MinimizeBox = `$false
|
||||
`$form.TopMost = `$true
|
||||
`$form.BackColor = [System.Drawing.Color]::FromArgb(24, 24, 37)
|
||||
`$lTitle = New-Object System.Windows.Forms.Label
|
||||
`$lTitle.Text = '$annTitle'
|
||||
`$lTitle.Font = New-Object System.Drawing.Font('Segoe UI', 13, [System.Drawing.FontStyle]::Bold)
|
||||
`$lTitle.ForeColor = [System.Drawing.Color]::White
|
||||
`$lTitle.Location = New-Object System.Drawing.Point(20, 20)
|
||||
`$lTitle.Size = New-Object System.Drawing.Size(460, 36)
|
||||
`$form.Controls.Add(`$lTitle)
|
||||
`$lMsg = New-Object System.Windows.Forms.Label
|
||||
`$lMsg.Text = '$annMessage'
|
||||
`$lMsg.Font = New-Object System.Drawing.Font('Segoe UI', 10)
|
||||
`$lMsg.ForeColor = [System.Drawing.Color]::FromArgb(200, 200, 220)
|
||||
`$lMsg.Location = New-Object System.Drawing.Point(20, 66)
|
||||
`$lMsg.Size = New-Object System.Drawing.Size(460, 155)
|
||||
`$lMsg.AutoSize = `$false
|
||||
`$form.Controls.Add(`$lMsg)
|
||||
`$lHint = New-Object System.Windows.Forms.Label
|
||||
`$lHint.Text = 'Bitte lesen und Kenntnisnahme bestaetigen.'
|
||||
`$lHint.Font = New-Object System.Drawing.Font('Segoe UI', 8, [System.Drawing.FontStyle]::Italic)
|
||||
`$lHint.ForeColor = [System.Drawing.Color]::FromArgb(130, 130, 150)
|
||||
`$lHint.Location = New-Object System.Drawing.Point(20, 228)
|
||||
`$lHint.Size = New-Object System.Drawing.Size(460, 20)
|
||||
`$form.Controls.Add(`$lHint)
|
||||
`$btn = New-Object System.Windows.Forms.Button
|
||||
`$btn.Text = 'Gelesen und bestaetigt'
|
||||
`$btn.Font = New-Object System.Drawing.Font('Segoe UI', 10, [System.Drawing.FontStyle]::Bold)
|
||||
`$btn.ForeColor = [System.Drawing.Color]::White
|
||||
`$btn.BackColor = [System.Drawing.Color]::FromArgb($accentColor)
|
||||
`$btn.FlatStyle = 'Flat'
|
||||
`$btn.Location = New-Object System.Drawing.Point(20, 255)
|
||||
`$btn.Size = New-Object System.Drawing.Size(460, 40)
|
||||
`$btn.DialogResult = [System.Windows.Forms.DialogResult]::OK
|
||||
`$form.Controls.Add(`$btn)
|
||||
`$form.AcceptButton = `$btn
|
||||
`$r = `$form.ShowDialog()
|
||||
if (`$r -eq [System.Windows.Forms.DialogResult]::OK) {
|
||||
`$b = [System.Text.Encoding]::UTF8.GetBytes('{"hostname":"' + `$env:COMPUTERNAME + '"}')
|
||||
`$req = [System.Net.WebRequest]::Create('$ServerUrl/api/announcements/$annId/ack-agent')
|
||||
`$req.Method = 'POST'; `$req.ContentType = 'application/json'
|
||||
`$req.Headers.Add('X-Agent-Key','$AgentKey')
|
||||
`$req.ContentLength = `$b.Length
|
||||
`$s = `$req.GetRequestStream(); `$s.Write(`$b,0,`$b.Length); `$s.Close()
|
||||
try { `$req.GetResponse().Close() } catch {}
|
||||
}
|
||||
"@
|
||||
$scriptFile = "C:\ProgramData\IT Nexus Agent\ann_$annId.ps1"
|
||||
$dialogScript | Out-File -FilePath $scriptFile -Encoding UTF8 -Force
|
||||
$loggedUser = (Get-CimInstance Win32_ComputerSystem).UserName
|
||||
if ($loggedUser) {
|
||||
$taskName = "ITNexus-Ann-$annId"
|
||||
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
|
||||
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-ExecutionPolicy Bypass -WindowStyle Normal -File `"$scriptFile`""
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(2)
|
||||
$principal = New-ScheduledTaskPrincipal -UserId $loggedUser -LogonType Interactive -RunLevel Limited
|
||||
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 60) -StartWhenAvailable
|
||||
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null
|
||||
Write-Log "ANNOUNCEMENT: Sofort-Dialog gestartet fuer $loggedUser - ID $annId"
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
# Stiller Fehler - nicht kritisch
|
||||
}
|
||||
}
|
||||
|
||||
# Announcement-Watcher-Task einrichten (alle 15 Sek, bleibt dauerhaft aktiv)
|
||||
try {
|
||||
$watcherName = 'IT Nexus Announcement Watcher'
|
||||
$watcherScript = 'C:\ProgramData\IT Nexus Agent\ann-watcher.ps1'
|
||||
|
||||
# Watcher-Script vom Server laden (immer aktuell)
|
||||
Invoke-WebRequest -Uri "$ServerUrl/api/monitoring/ann-watcher" `
|
||||
-Headers @{ 'X-Agent-Key' = $AgentKey } `
|
||||
-OutFile $watcherScript -TimeoutSec 15 -ErrorAction SilentlyContinue
|
||||
|
||||
# Task registrieren falls noch nicht vorhanden
|
||||
if (-not (Get-ScheduledTask -TaskName $watcherName -ErrorAction SilentlyContinue)) {
|
||||
$wAct = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-ExecutionPolicy Bypass -NonInteractive -WindowStyle Hidden -File `"$watcherScript`""
|
||||
$wTrg = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Seconds 15) -Once -At (Get-Date)
|
||||
$wSet = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Seconds 14) -MultipleInstances IgnoreNew -StartWhenAvailable
|
||||
$wPri = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
|
||||
Register-ScheduledTask -TaskName $watcherName -Action $wAct -Trigger $wTrg -Settings $wSet -Principal $wPri -Force | Out-Null
|
||||
Write-Log "ANNOUNCEMENT: Watcher-Task registriert (alle 15 Sekunden)"
|
||||
}
|
||||
} catch {
|
||||
Write-Log "ANNOUNCEMENT WATCHER ERROR: $($_.Exception.Message)"
|
||||
}
|
||||
103
agent/setup.iss
Normal file
103
agent/setup.iss
Normal file
@@ -0,0 +1,103 @@
|
||||
#define MyAppName "IT Nexus Agent"
|
||||
#define MyAppVersion "1.2.4"
|
||||
#define MyAppPublisher "Cereda Systems GmbH"
|
||||
#define MyAppURL "https://it-nexus.cereda-systems.de"
|
||||
#define MyAppExeName "it-nexus-agent.ps1"
|
||||
#define InstallDir "{commonappdata}\IT Nexus Agent"
|
||||
|
||||
[Setup]
|
||||
AppId={{B3F7A2C1-4E8D-4F2A-9B1C-7D3E5F6A8B2C}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
DefaultDirName={#InstallDir}
|
||||
DisableDirPage=yes
|
||||
DefaultGroupName={#MyAppName}
|
||||
DisableProgramGroupPage=yes
|
||||
OutputDir=..\dist
|
||||
OutputBaseFilename=IT-Nexus-Agent-Setup-v{#MyAppVersion}
|
||||
SetupIconFile=
|
||||
Compression=lzma2/ultra64
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
WizardSizePercent=120
|
||||
PrivilegesRequired=admin
|
||||
UninstallDisplayName={#MyAppName}
|
||||
UninstallDisplayIcon={app}\it-nexus-agent.ps1
|
||||
CloseApplications=no
|
||||
DisableWelcomePage=no
|
||||
WizardImageFile=compiler:WizModernImage.bmp
|
||||
WizardSmallImageFile=compiler:WizModernSmallImage.bmp
|
||||
|
||||
[Languages]
|
||||
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
||||
|
||||
[Files]
|
||||
Source: "it-nexus-agent.ps1"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "config.json.template"; DestDir: "{app}"; DestName: "config.json"; Flags: ignoreversion onlyifdoesntexist
|
||||
|
||||
[Run]
|
||||
Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -NonInteractive -Command ""Unregister-ScheduledTask -TaskName 'IT Nexus Agent' -Confirm:$false -ErrorAction SilentlyContinue; $a = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -NonInteractive -WindowStyle Hidden -File \""{app}\it-nexus-agent.ps1\""'; $t = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 1) -Once -At (Get-Date); $s = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2) -MultipleInstances IgnoreNew -StartWhenAvailable; $p = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest; Register-ScheduledTask -TaskName 'IT Nexus Agent' -Action $a -Trigger $t -Settings $s -Principal $p -Force; Start-ScheduledTask -TaskName 'IT Nexus Agent'"""; Flags: runhidden waituntilterminated; StatusMsg: "Registriere Windows Scheduled Task..."
|
||||
|
||||
[UninstallRun]
|
||||
Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -NonInteractive -Command ""Unregister-ScheduledTask -TaskName 'IT Nexus Agent' -Confirm:$false -ErrorAction SilentlyContinue"""; Flags: runhidden waituntilterminated
|
||||
|
||||
[Code]
|
||||
var
|
||||
ServerUrlPage: TInputQueryWizardPage;
|
||||
AgentKeyPage: TInputQueryWizardPage;
|
||||
|
||||
procedure InitializeWizard;
|
||||
begin
|
||||
ServerUrlPage := CreateInputQueryPage(wpWelcome,
|
||||
'Server-Konfiguration',
|
||||
'Gib die IT Nexus Server-Adresse ein.',
|
||||
'');
|
||||
ServerUrlPage.Add('Server URL:', False);
|
||||
ServerUrlPage.Values[0] := 'https://it-nexus.cereda-systems.de';
|
||||
|
||||
AgentKeyPage := CreateInputQueryPage(ServerUrlPage.ID,
|
||||
'API Key',
|
||||
'Gib den Agent API Key ein. Diesen findest du in den IT Nexus Einstellungen.',
|
||||
'');
|
||||
AgentKeyPage.Add('Agent API Key:', False);
|
||||
AgentKeyPage.Values[0] := 'itx-4CPJPTHmCfdrL9D62WacCATEvuvULXcp7ECMpSaNUjsS344F6_L4Ug';
|
||||
end;
|
||||
|
||||
function NextButtonClick(CurPageID: Integer): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
if CurPageID = ServerUrlPage.ID then begin
|
||||
if ServerUrlPage.Values[0] = '' then begin
|
||||
MsgBox('Bitte gib eine Server URL ein.', mbError, MB_OK);
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
if CurPageID = AgentKeyPage.ID then begin
|
||||
if AgentKeyPage.Values[0] = '' then begin
|
||||
MsgBox('Bitte gib einen API Key ein.', mbError, MB_OK);
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var
|
||||
ConfigFile: string;
|
||||
Config: TStringList;
|
||||
begin
|
||||
if CurStep = ssPostInstall then begin
|
||||
ConfigFile := ExpandConstant('{app}\config.json');
|
||||
Config := TStringList.Create;
|
||||
try
|
||||
Config.Add('{');
|
||||
Config.Add(' "server_url": "' + ServerUrlPage.Values[0] + '",');
|
||||
Config.Add(' "agent_key": "' + AgentKeyPage.Values[0] + '"');
|
||||
Config.Add('}');
|
||||
Config.SaveToFile(ConfigFile);
|
||||
finally
|
||||
Config.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
8
agent/uninstall.ps1
Normal file
8
agent/uninstall.ps1
Normal file
@@ -0,0 +1,8 @@
|
||||
# IT Nexus Agent - Uninstaller
|
||||
$InstallDir = "C:\Program Files\IT Nexus Agent"
|
||||
$TaskName = "IT Nexus Agent"
|
||||
|
||||
Write-Host "=== IT Nexus Agent Deinstallation ===" -ForegroundColor Yellow
|
||||
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path $InstallDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "Agent entfernt." -ForegroundColor Green
|
||||
Reference in New Issue
Block a user