# Auto-Logon einrichten — schliesst die letzte Luecke der Boot-Pipeline. # # WOZU: `OilTradingServer` und `HyperliquidDashboard` haengen an einem LOGON- # Trigger. Nach einem Windows-Update-Reboot laeuft nichts, bis sich jemand # anmeldet — real in der Nacht zum 2026-07-20 passiert (Reboot 01:30, Server bis # 07:42 tot, nur der broker-seitige SL schuetzte, -95,48 EUR). Ein Task ohne # angemeldete Sitzung hilft NICHT: der Bot braucht das laufende MT5-TERMINAL, # und das ist eine GUI-Anwendung — es braucht eine echte Desktop-Sitzung. # # ⚠⚠ WARUM SYSINTERNALS UND NICHT DIE REGISTRY. Der verbreitete Weg schreibt # das Passwort als `DefaultPassword` im KLARTEXT nach HKLM\...\Winlogon — dort # kann es jeder lokale Administrator und jedes Backup-Image lesen. Sysinternals # `Autologon` legt es als verschluesseltes LSA-Secret ab. # # ⚠ RESTRISIKO, das bleibt: nach dem Reboot steht eine ANGEMELDETE Sitzung mit # offenem MT5 und Live-Broker-Verbindung da. Schritt 2 sperrt deshalb den # Bildschirm — aber nur nach einem Auto-Logon, nicht nach jeder Anmeldung # (s. `autologon_lock.ps1`). # # AUFRUF (Fenster muss ALS ADMINISTRATOR laufen): # powershell -ExecutionPolicy Bypass -File tools\autologon_einrichten.ps1 # # ⚠ Das Passwort steht NICHT in dieser Datei und wird nirgends gespeichert — # es wird im GUI-Dialog von Autologon eingegeben. # # ⚠⚠ ZWEI FEHLER AUS DEM ERSTEN VERSUCH (2026-08-07), hier behoben: # 1. `$ErrorActionPreference = 'Stop'` PLUS `schtasks /Delete` auf eine noch # nicht existierende Aufgabe = das Skript brach ab, BEVOR /Create lief. # Native Programme schreiben nach stderr, und PowerShell macht daraus unter # 'Stop' einen Abbruch. Jetzt wird vorher geprueft, ob es sie ueberhaupt gibt. # 2. Die Erfolgsmeldung log: fehlendes `DefaultPassword` wurde als # "LSA-Secret ✅" gemeldet — dabei war schlicht GAR NICHTS gesetzt. Jetzt # ist `AutoAdminLogon = 1` die Bedingung, und erst danach wird ueberhaupt # ueber die Speicherart geurteilt. # AUFRUF-VARIANTEN: # ... -File tools\autologon_einrichten.ps1 GUI-Dialog (Standard) # ... -File tools\autologon_einrichten.ps1 -Direkt ohne Dialog, Passwort # wird hier abgefragt # ⚠ `-Direkt` ist der zuverlaessige Weg. Der Dialog OEFFNET sich zwar # (Fenstertitel "Autologon - Sysinternals", verifiziert), muss aber mit ENABLE # bestaetigt werden — wird er nur geschlossen, passiert nichts. # ⚠ Abwaegung bei `-Direkt`: Autologon 3.10 nimmt Benutzer/Domaene/Passwort als # Argumente. Das Passwort steht damit fuer den Moment des Aufrufs in der # Kommandozeile des Kindprozesses (fuer Administratoren kurz sichtbar). Es wird # NICHT in eine Datei geschrieben, nicht in die PowerShell-History (Read-Host) # und landet anschliessend als verschluesseltes LSA-Secret — nicht im Klartext # in der Registry. param([switch]$Direkt) $ErrorActionPreference = 'Stop' $hier = Split-Path -Parent $MyInvocation.MyCommand.Path $k = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' $t = 'OilAutoLogonLock' $id = [Security.Principal.WindowsIdentity]::GetCurrent() if (-not (New-Object Security.Principal.WindowsPrincipal($id)).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Host " ABBRUCH: Dieses Fenster hat keine Administratorrechte." -ForegroundColor Red exit 1 } $exe = Join-Path $hier 'autologon\Autologon64.exe' if (-not (Test-Path $exe)) { $exe = Join-Path $hier 'autologon\Autologon.exe' } if (-not (Test-Path $exe)) { Write-Host " ABBRUCH: Autologon.exe fehlt unter tools\autologon\." -ForegroundColor Red exit 1 } Write-Host "==================================================================" Write-Host " SCHRITT 1 - Auto-Logon aktivieren (verschluesseltes LSA-Secret)" Write-Host "==================================================================" Write-Host " Benutzer: $env:USERNAME Domaene: $env:COMPUTERNAME (lokal)" # Aktivierung ohne Dialog — als Funktion, damit sie auch als Rueckfall nach # einem abgebrochenen Dialog aufgerufen werden kann (sonst muesste der Nutzer # das Skript ein drittes Mal starten). function Invoke-DirektAktivierung { # ⚠ Read-Host -AsSecureString: die Eingabe erscheint nicht auf dem Schirm # und landet nicht in der PowerShell-History. $sec = Read-Host " Passwort fuer $env:USERNAME (Eingabe bleibt unsichtbar)" -AsSecureString $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($sec) try { $pw = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) if (-not $pw) { Write-Host " Kein Passwort eingegeben." -ForegroundColor Red return $false } Write-Host " Aktiviere Auto-Logon ..." # ⚠⚠ ZWEI FEHLER AUS DEM VORIGEN VERSUCH, hier behoben: # (a) `& $exe ...` WARTET BEI GUI-ANWENDUNGEN NICHT — das Skript las die # Registry, bevor Autologon ueberhaupt fertig war. # (b) `$null = ... 2>&1` hat die Rueckmeldung VERSCHLUCKT. Genau die # Information, die zur Diagnose noetig war, wurde weggeworfen. # Jetzt: warten, Exit-Code auswerten, Ausgabe zeigen. $log = Join-Path $env:TEMP 'autologon_out.txt' $p = Start-Process -FilePath $exe ` -ArgumentList $env:USERNAME, $env:COMPUTERNAME, $pw ` -Wait -PassThru -RedirectStandardOutput $log ` -RedirectStandardError "$log.err" -WindowStyle Hidden Write-Host " Autologon ExitCode: $($p.ExitCode)" foreach ($f in @($log, "$log.err")) { if ((Test-Path $f) -and (Get-Item $f).Length -gt 0) { Write-Host " Ausgabe: $((Get-Content $f -Raw).Trim())" } Remove-Item $f -EA SilentlyContinue } return $true } finally { # Klartext so kurz wie moeglich im Speicher halten [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) Remove-Variable pw -ErrorAction SilentlyContinue } } Write-Host "" if ($Direkt) { if (-not (Invoke-DirektAktivierung)) { exit 1 } } else { Write-Host " Es oeffnet sich gleich der Autologon-Dialog." -ForegroundColor Cyan Write-Host " --> Passwort eintragen und auf ENABLE klicken." -ForegroundColor Cyan Write-Host " (Nur schliessen reicht NICHT - dann passiert nichts." Write-Host " Zuverlaessiger: Skript mit -Direkt aufrufen.)" Write-Host "" Start-Process -FilePath $exe -ArgumentList '/accepteula' -Wait } # ── Ergebnis ehrlich pruefen ──────────────────────────────────────────── $an = (Get-ItemProperty -Path $k -Name AutoAdminLogon -EA SilentlyContinue).AutoAdminLogon $user = (Get-ItemProperty -Path $k -Name DefaultUserName -EA SilentlyContinue).DefaultUserName $klartext = (Get-ItemProperty -Path $k -Name DefaultPassword -EA SilentlyContinue).DefaultPassword $aktiv = ($an -eq '1') Write-Host "" Write-Host " AutoAdminLogon : $(if ($an) { $an } else { '(nicht gesetzt)' })" Write-Host " DefaultUserName : $(if ($user) { $user } else { '(nicht gesetzt)' })" # ⚠ RUECKFALL statt Sackgasse: schlaegt der Dialog-Weg fehl, wird hier direkt # angeboten, es ohne Dialog zu erledigen — sonst muesste das Skript ein drittes # Mal von Hand gestartet werden (real zweimal passiert). if (-not $aktiv -and -not $Direkt) { Write-Host "" Write-Host " ==> Der Dialog wurde ohne 'Enable' geschlossen." -ForegroundColor Yellow $a = Read-Host " Jetzt ohne Dialog erledigen? (j/n)" if ($a -match '^[jJyY]') { if (Invoke-DirektAktivierung) { $an = (Get-ItemProperty -Path $k -Name AutoAdminLogon -EA SilentlyContinue).AutoAdminLogon $user = (Get-ItemProperty -Path $k -Name DefaultUserName -EA SilentlyContinue).DefaultUserName $klartext = (Get-ItemProperty -Path $k -Name DefaultPassword -EA SilentlyContinue).DefaultPassword $aktiv = ($an -eq '1') Write-Host "" Write-Host " AutoAdminLogon : $(if ($an) { $an } else { '(nicht gesetzt)' })" Write-Host " DefaultUserName : $(if ($user) { $user } else { '(nicht gesetzt)' })" } } } # ── Letzter Ausweg: Registry-Weg ──────────────────────────────────────── # ⚠⚠ BEWUSST ALS LETZTE OPTION und nur nach ausdruecklicher Zustimmung. Hier # landet das Passwort im KLARTEXT unter HKLM\...\Winlogon\DefaultPassword — # lesbar fuer jeden lokalen Administrator und in jedem Backup-Image. Der einzige # Vorteil: er funktioniert immer, ohne Fremdprogramm. Wenn Autologon (der # sichere Weg) partout nicht greift, ist das die Alternative — die Entscheidung # gehoert dem Nutzer, nicht dem Skript. if (-not $aktiv) { Write-Host "" Write-Host " ==> AUTO-LOGON IST NICHT AKTIV." -ForegroundColor Yellow Write-Host " Sysinternals Autologon hat nichts geschrieben." Write-Host "" Write-Host " ALTERNATIVE: der Registry-Weg." -ForegroundColor Cyan Write-Host " ⚠ Dabei steht das Passwort im KLARTEXT in der Registry" -ForegroundColor Yellow Write-Host " (HKLM\...\Winlogon\DefaultPassword). Jeder lokale Admin und" Write-Host " jedes Backup-Image kann es lesen. Er funktioniert dafuer immer." $a = Read-Host " Registry-Weg jetzt verwenden? (j/n)" if ($a -notmatch '^[jJyY]') { Write-Host " Abgebrochen. Schritt 2 uebersprungen." exit 1 } $sec = Read-Host " Passwort fuer $env:USERNAME (Eingabe bleibt unsichtbar)" -AsSecureString $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($sec) try { $pw2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) if (-not $pw2) { Write-Host " Kein Passwort." -ForegroundColor Red; exit 1 } Set-ItemProperty -Path $k -Name AutoAdminLogon -Value '1' -Type String Set-ItemProperty -Path $k -Name DefaultUserName -Value $env:USERNAME -Type String Set-ItemProperty -Path $k -Name DefaultDomainName -Value $env:COMPUTERNAME -Type String Set-ItemProperty -Path $k -Name DefaultPassword -Value $pw2 -Type String } finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) Remove-Variable pw2 -EA SilentlyContinue } $an = (Get-ItemProperty -Path $k -Name AutoAdminLogon -EA SilentlyContinue).AutoAdminLogon $aktiv = ($an -eq '1') Write-Host "" Write-Host " AutoAdminLogon : $an" Write-Host " ⚠ DefaultPassword steht jetzt im KLARTEXT in der Registry." -ForegroundColor Yellow Write-Host " Entfernen mit: Remove-ItemProperty -Path '$k' -Name DefaultPassword" } if (-not $aktiv) { Write-Host " ==> Auch das hat nicht gegriffen. Schritt 2 uebersprungen." -ForegroundColor Red exit 1 } if ($klartext) { Write-Host " DefaultPassword : ⚠ KLARTEXT in der Registry!" -ForegroundColor Yellow } else { Write-Host " DefaultPassword : nicht im Klartext (LSA-Secret) ✅" -ForegroundColor Green } # ── Schritt 2: Bildschirmsperre nach dem Auto-Logon ───────────────────── Write-Host "" Write-Host "==================================================================" Write-Host " SCHRITT 2 - Bildschirm nach dem Auto-Logon sperren" Write-Host "==================================================================" # ⚠ Erst pruefen, dann loeschen. `schtasks /Delete` auf eine fehlende Aufgabe # schreibt nach stderr und wuerde unter $ErrorActionPreference='Stop' abbrechen. $vorhanden = $false try { $null = & schtasks /Query /TN $t 2>&1 $vorhanden = ($LASTEXITCODE -eq 0) } catch { $vorhanden = $false } if ($vorhanden) { $null = & schtasks /Delete /TN $t /F 2>&1 Write-Host " alte Aufgabe entfernt" } $lock = Join-Path $hier 'autologon_lock.ps1' $cmd = "powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$lock`"" $null = & schtasks /Create /TN $t /SC ONLOGON /RU "$env:USERNAME" /DELAY 0000:30 /TR $cmd /F 2>&1 if ($LASTEXITCODE -eq 0) { Write-Host " Aufgabe '$t' angelegt." -ForegroundColor Green Write-Host " Sperrt 30 s nach der Anmeldung - aber NUR, wenn der Rechner" Write-Host " gerade gebootet hat. Nach manueller Anmeldung passiert nichts." Write-Host " Die Sitzung laeuft weiter: MT5 und beide Server arbeiten." } else { Write-Host " ⚠ Aufgabe konnte nicht angelegt werden (Code $LASTEXITCODE)." -ForegroundColor Yellow } Write-Host "" Write-Host " Rueckgaengig:" Write-Host " $exe /accepteula (dann Disable)" Write-Host " schtasks /Delete /TN $t /F"