From 8f208ed0da1d20af4972baaf6cfd32155d4db3a5 Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Sat, 25 Jul 2026 22:11:39 +0200 Subject: [PATCH] fix(worker-windows): Autostart brach die ganze Installation ab Beim Commander live aufgetreten: Der Installer meldete "FEHLER: FEHLER: Zugriff verweigert" samt dem Tipp, die IP koenne falsch sein - und das, NACHDEM Worker-Code, Abhaengigkeiten und HandBrake schon fertig waren. Die IP war also nie das Problem. URSACHE: schtasks /create mit /tn "RippyWorker" legt die Aufgabe im WURZELORDNER der Aufgabenplanung an, und das verlangt Administratorrechte. Der Installer laeuft normal ohne. schtasks schrieb "FEHLER: Zugriff verweigert." nach stderr, und weil im Skript $ErrorActionPreference = "Stop" steht, machte PowerShell daraus einen TERMINIERENDEN Fehler - der catch-Block riss damit die komplette Installation ab, obwohl nur der Autostart fehlte. Das doppelte "FEHLER: FEHLER:" war der Hinweis: der aeussere Handler setzt sein Praefix vor eine Meldung, die selbst schon mit "FEHLER:" begann, also aus schtasks kam. FIX, zwei Teile: 1. Autostart ueber den Autostart-ORDNER statt schtasks. Eine Verknuepfung in [Environment]::GetFolderPath("Startup") braucht NIE Adminrechte - und der Nutzer kann sie dort selbst sehen und loeschen. Auf diesem Windows-PC gegengeprueft: Verknuepfung angelegt (1047 Bytes) mit Admin=False. 2. Ein Fehlschlag beim Autostart ist jetzt eine WARNUNG in eigenem try/catch, kein Abbruch. Der Worker ist zu dem Zeitpunkt fertig und startbar, und der Text sagt das auch - plus den Handweg (shell:startup). In BEIDEN Installern (install-gui.ps1 und install.ps1, dort mit -Autostart) - der CLI-Weg hatte denselben Fehler. uninstall.ps1 raeumt jetzt die Verknuepfung weg UND versucht weiter schtasks /delete, damit aeltere Installationen sauber verschwinden. RippyWorkerSetup.exe neu gebaut (50688 -> 52736 Bytes): die GUI ist in der .exe eingebettet, ohne Rebuild wirkt der Fix beim Nutzer nicht. Nebenbei: build-exe.ps1 hatte zwei Gedankenstriche. Ausgelieferte .ps1 muessen reines ASCII sein (PowerShell 5.1 liest sie als ANSI) - jetzt sind alle drei Skripte ASCII-rein und parsen fehlerfrei. Co-Authored-By: Claude Opus 5 --- deploy/worker-windows/RippyWorkerSetup.exe | Bin 50688 -> 52736 bytes deploy/worker-windows/build-exe.ps1 | 118 ++++++++++----------- deploy/worker-windows/install-gui.ps1 | 37 ++++++- deploy/worker-windows/install.ps1 | 26 ++++- 4 files changed, 117 insertions(+), 64 deletions(-) diff --git a/deploy/worker-windows/RippyWorkerSetup.exe b/deploy/worker-windows/RippyWorkerSetup.exe index e35558a669529feb4c2946c3b54d83c0f1c6e4db..9ac3fba40dac827ecaaa3fb8293e7f9c768cd22e 100644 GIT binary patch delta 2305 zcma)8-)kII6rN2n+7yaPX)9Dboh-U*v(p&-0gHjI$)t&-X~-s7s6X%QoSm8O%$@bl zovdl8)5lUo41*71AFV>EA}k1^P!XSs_zx&058|uuK6&o!YcBF0?#?~uJLi1o zJ9G8p16OYx`1G3o(s8_~<=3t@Ryb5Rq-nQl1Nxiy?(W>$Jbdl0rq$KPuBM$iv2*fB zsu$j!`0Ez!0R3*K*9)f#-=^OeUMT#Q-Ye+O|4awewMf4)?J=$Mk)|DA*0cgW3r!oJ zruCVb^yJMKd#hu+r^a5N>CG5_7L!S+#WIW}6SA_2qRnIMv|{c6a@j(`kwb}Ni~<_y zl)*5J2`RSWGOS?`Zee9fVgQweP&5%rZ-ySPtTO3B=`E9Qc_QQi*?Fg0J&ST7^lcRC z-;!Qe{^E{aPRgLKd7aL7BNS~EhR@r287ig_p{O;b7jme}ume}1$z;=o%U32Q6$psA z4Yr5iV8>@%B8Aa%n1#UN2pIYj1wmip6q)ZcWeE8cwCEv%tx&j(+sKWH-r@QWg#==> zC_>s9$;SD$`4w|*3b@yFW&TD)OBS^wV*>JPa=3ywkTPe(%qzz9YsSp<%&Smhaf{3b zFc$`aaw#gSa|E&FpcE*Pm#YvplfF?n-4w_qj#vyl38y9BlOr8`bYvF%AZ9Os#>UzO zbGeV1Jc!FoBC_-`N(Bm^C7kTl?7-t*Bn6Y95J-Wd0rPtd<=Lc6`3&Qh z1Rjcj`4GCC-W}vdErf>_p@>}OTO&yH1#@xPT&u!`*b!c<3|qsWPSvp}Q@J35_5S584U7B+&-gyI8wR9MRrG1=dno3m!U zb}m^rSN2c^D&(~rx;_wJkoXiwQO1v8$PXaT(sQ88#0VQy#$Y9um*^HT7kDh-e$@L% z?_eS%;bs996@!sbJ*q=1MwcQ~)Lf@Nnab+Ev*lqDagdYS}Cdm8tlk zlcD}3xd1(EtsA+-uodi9&RZ9;DWO6Qoi7{prtmt_sJrO<4<98(qoYN#V9aIhU3V#I z%~+Q9U@X(g=LYEe_aYrN)|nu!$TW2}z0)Xf?CZf$^67DB-lIZN|86UndAriy{%7W? zN(wn?V|x4LXLNo4*XnEwO9~!9y17w4k5w0A$0Lgm>Gpm;}2=@6o7ciVq z21X#ih=GC40LU)Un*4E%*5&}F2ii;pTAPjZ?x<|$3E9awSv68OsW>^KB(XTVSV2Fz zC^fMpRY5;ZLBAwVK`AJ+prA55zbHGkNC_xXq@a|bq~e)ZT#}fR)F}9umgxGG=HzfqwvW~n3kIoHNJ`CAaLmh1%}FWE zOV`v>+MF1>+fBg9ymj^bd|sb5mYa6De%olVS!YQMhtLzK&p^KW2VyHsR1{ PNG -> ICO-Container -$bmp = New-Object System.Drawing.Bitmap 256, 256 -$g = [System.Drawing.Graphics]::FromImage($bmp) -$g.SmoothingMode = "AntiAlias" -$g.Clear([System.Drawing.Color]::Transparent) -$g.FillEllipse((New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(99, 102, 241))), 8, 8, 240, 240) -$g.FillEllipse((New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(147, 51, 234))), 40, 40, 176, 176) -$g.FillEllipse([System.Drawing.Brushes]::White, 104, 104, 48, 48) -$ms = New-Object System.IO.MemoryStream -$bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) -$png = $ms.ToArray() - -$icoStream = New-Object System.IO.MemoryStream -$bw = New-Object System.IO.BinaryWriter $icoStream -$bw.Write([UInt16]0); $bw.Write([UInt16]1); $bw.Write([UInt16]1) # ICONDIR -$bw.Write([Byte]0); $bw.Write([Byte]0); $bw.Write([Byte]0); $bw.Write([Byte]0) # 256x256, colors, res -$bw.Write([UInt16]1); $bw.Write([UInt16]32) # planes, bpp -$bw.Write([UInt32]$png.Length); $bw.Write([UInt32]22) # size, offset -$bw.Write($png); $bw.Flush() -[System.IO.File]::WriteAllBytes("$PSScriptRoot\rippy.ico", $icoStream.ToArray()) -Write-Host "rippy.ico erzeugt ($($png.Length) Bytes PNG)" - -# 2. ps2exe sicherstellen — TLS 1.2 ist der Fix fuer den NuGet-Bootstrap-Fehler -[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072 -if (-not (Get-Module -ListAvailable ps2exe)) { - Write-Host "Bootstrappe NuGet + PSGallery ..." - try { Get-PackageProvider -Name NuGet -ErrorAction Stop | Out-Null } - catch { Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null } - Set-PSRepository -Name PSGallery -InstallationPolicy Trusted -ErrorAction SilentlyContinue - Write-Host "Installiere ps2exe ..." - Install-Module ps2exe -Scope CurrentUser -Force -AllowClobber -} -Import-Module ps2exe - -# 3. Kompilieren (WinForms -> noConsole + STA, Icon eingebettet) -Invoke-ps2exe -inputFile $guiSrc -outputFile "$PSScriptRoot\RippyWorkerSetup.exe" ` - -iconFile "$PSScriptRoot\rippy.ico" -noConsole -STA ` - -title "Rippy Worker Setup" -product "Rippy" -company "Rippy" -version "1.0.0.0" - -if (Test-Path "$PSScriptRoot\RippyWorkerSetup.exe") { - Write-Host "OK: RippyWorkerSetup.exe = $((Get-Item "$PSScriptRoot\RippyWorkerSetup.exe").Length) Bytes" -} else { - Write-Host "FEHLER: keine .exe erzeugt" -} +# Baut rippy.ico + RippyWorkerSetup.exe aus install-gui.ps1 (ps2exe). +# +# WANN NEU BAUEN: nur wenn sich install-gui.ps1 (die Installer-Oberflaeche) +# aendert. NICHT bei MakeMKV-/HandBrake-Updates - die .exe holt HandBrake zur +# Laufzeit (GitHub latest) und den Worker-Code live von Rippy, friert also +# keine Versionen ein. +# AUSFUEHREN AUF WINDOWS (eine Windows-.exe kann nicht von Linux gebaut werden): +# powershell -ExecutionPolicy Bypass -File build-exe.ps1 +# Danach RippyWorkerSetup.exe committen (die API serviert sie). +$ErrorActionPreference = "Stop" +Add-Type -AssemblyName System.Drawing +Set-Location $PSScriptRoot + +$guiSrc = Join-Path $PSScriptRoot "install-gui.ps1" + +# 1. Rippy-Disc-Icon 256x256 zeichnen -> PNG -> ICO-Container +$bmp = New-Object System.Drawing.Bitmap 256, 256 +$g = [System.Drawing.Graphics]::FromImage($bmp) +$g.SmoothingMode = "AntiAlias" +$g.Clear([System.Drawing.Color]::Transparent) +$g.FillEllipse((New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(99, 102, 241))), 8, 8, 240, 240) +$g.FillEllipse((New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(147, 51, 234))), 40, 40, 176, 176) +$g.FillEllipse([System.Drawing.Brushes]::White, 104, 104, 48, 48) +$ms = New-Object System.IO.MemoryStream +$bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) +$png = $ms.ToArray() + +$icoStream = New-Object System.IO.MemoryStream +$bw = New-Object System.IO.BinaryWriter $icoStream +$bw.Write([UInt16]0); $bw.Write([UInt16]1); $bw.Write([UInt16]1) # ICONDIR +$bw.Write([Byte]0); $bw.Write([Byte]0); $bw.Write([Byte]0); $bw.Write([Byte]0) # 256x256, colors, res +$bw.Write([UInt16]1); $bw.Write([UInt16]32) # planes, bpp +$bw.Write([UInt32]$png.Length); $bw.Write([UInt32]22) # size, offset +$bw.Write($png); $bw.Flush() +[System.IO.File]::WriteAllBytes("$PSScriptRoot\rippy.ico", $icoStream.ToArray()) +Write-Host "rippy.ico erzeugt ($($png.Length) Bytes PNG)" + +# 2. ps2exe sicherstellen - TLS 1.2 ist der Fix fuer den NuGet-Bootstrap-Fehler +[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072 +if (-not (Get-Module -ListAvailable ps2exe)) { + Write-Host "Bootstrappe NuGet + PSGallery ..." + try { Get-PackageProvider -Name NuGet -ErrorAction Stop | Out-Null } + catch { Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null } + Set-PSRepository -Name PSGallery -InstallationPolicy Trusted -ErrorAction SilentlyContinue + Write-Host "Installiere ps2exe ..." + Install-Module ps2exe -Scope CurrentUser -Force -AllowClobber +} +Import-Module ps2exe + +# 3. Kompilieren (WinForms -> noConsole + STA, Icon eingebettet) +Invoke-ps2exe -inputFile $guiSrc -outputFile "$PSScriptRoot\RippyWorkerSetup.exe" ` + -iconFile "$PSScriptRoot\rippy.ico" -noConsole -STA ` + -title "Rippy Worker Setup" -product "Rippy" -company "Rippy" -version "1.0.0.0" + +if (Test-Path "$PSScriptRoot\RippyWorkerSetup.exe") { + Write-Host "OK: RippyWorkerSetup.exe = $((Get-Item "$PSScriptRoot\RippyWorkerSetup.exe").Length) Bytes" +} else { + Write-Host "FEHLER: keine .exe erzeugt" +} diff --git a/deploy/worker-windows/install-gui.ps1 b/deploy/worker-windows/install-gui.ps1 index 08cdece..17df0f9 100644 --- a/deploy/worker-windows/install-gui.ps1 +++ b/deploy/worker-windows/install-gui.ps1 @@ -199,6 +199,9 @@ if (-not `$Force) { if ([System.Windows.Forms.MessageBox]::Show("Rippy-Worker '$ Add-Type -AssemblyName System.Windows.Forms Get-CimInstance Win32_Process | Where-Object { `$_.ExecutablePath -like "`$PSScriptRoot*" } | ForEach-Object { Stop-Process -Id `$_.ProcessId -Force -ErrorAction SilentlyContinue } Start-Sleep 2 +# Autostart-Verknuepfung entfernen (neuer Weg) ... +try { Remove-Item -Force (Join-Path ([Environment]::GetFolderPath("Startup")) "RippyWorker.lnk") -ErrorAction Stop } catch {} +# ... und die geplante Aufgabe aus aelteren Installationen, falls vorhanden. schtasks /delete /tn "RippyWorker" /f 2>`$null | Out-Null try { Invoke-RestMethod -Method Delete "http://$rHost/api/workers/$wName" -TimeoutSec 5 | Out-Null } catch {} Set-Location (Split-Path `$PSScriptRoot -Parent) @@ -207,10 +210,38 @@ Remove-Item -Recurse -Force `$PSScriptRoot "@ Set-Content -Path "uninstall.ps1" -Value $uninstall -Encoding ASCII - # 6. Autostart + # 6. Autostart ueber den Autostart-ORDNER, nicht ueber schtasks. + # + # Befund 25.07.2026 (auf dem Commander-PC aufgetreten): schtasks /create + # mit /tn "RippyWorker" legt die Aufgabe im WURZELORDNER der + # Aufgabenplanung an, und das verlangt Administratorrechte. Der + # Installer laeuft normal ohne. schtasks schrieb deshalb + # "FEHLER: Zugriff verweigert." nach stderr, und weil oben + # $ErrorActionPreference = "Stop" steht, wurde daraus ein Abbruch der + # GESAMTEN Installation - obwohl alles ausser dem Autostart fertig war. + # Der Nutzer sah nur "FEHLER: FEHLER: Zugriff verweigert" samt dem + # irrefuehrenden Tipp, die IP koenne falsch sein. + # + # Der Autostart-Ordner braucht NIE Adminrechte, und der Nutzer kann die + # Verknuepfung dort selbst sehen und loeschen. Zwei Fliegen. if ($chkAuto.Checked) { - schtasks /create /f /tn "RippyWorker" /tr "`"$InstallDir\start-tray.bat`"" /sc onlogon | Out-Null - Log "Autostart eingerichtet (Start bei Anmeldung)." + try { + $autostartOrdner = [Environment]::GetFolderPath("Startup") + $verknuepfung = Join-Path $autostartOrdner "RippyWorker.lnk" + $wsh = New-Object -ComObject WScript.Shell + $lnk = $wsh.CreateShortcut($verknuepfung) + $lnk.TargetPath = (Join-Path $InstallDir "start-tray.bat") + $lnk.WorkingDirectory = $InstallDir + $lnk.Description = "Rippy Encoding-Worker" + $lnk.Save() + Log "Autostart eingerichtet (startet bei der Anmeldung)." + } catch { + # Nur eine Warnung: der Worker selbst ist fertig und startbar. + Log "HINWEIS: Autostart konnte nicht eingerichtet werden ($($_.Exception.Message))." + Log " Der Worker ist trotzdem fertig installiert und laeuft." + Log " Von Hand: start-tray.bat in den Autostart-Ordner verknuepfen" + Log " (Windows-Taste + R, dann shell:startup eingeben)." + } } Log "" diff --git a/deploy/worker-windows/install.ps1 b/deploy/worker-windows/install.ps1 index c6637b3..a058cc2 100644 --- a/deploy/worker-windows/install.ps1 +++ b/deploy/worker-windows/install.ps1 @@ -132,6 +132,9 @@ Get-CimInstance Win32_Process | Where-Object { `$_.ExecutablePath -like "`$PSScriptRoot*" } | ForEach-Object { Stop-Process -Id `$_.ProcessId -Force -ErrorAction SilentlyContinue } Start-Sleep 2 +# Autostart-Verknuepfung entfernen (neuer Weg) ... +try { Remove-Item -Force (Join-Path ([Environment]::GetFolderPath("Startup")) "RippyWorker.lnk") -ErrorAction Stop } catch {} +# ... und die geplante Aufgabe aus aelteren Installationen, falls vorhanden. schtasks /delete /tn "RippyWorker" /f 2>`$null | Out-Null try { Invoke-RestMethod -Method Delete "http://$RippyHost/api/workers/$WorkerName" -TimeoutSec 5 | Out-Null @@ -145,9 +148,28 @@ Set-Content -Path "uninstall.ps1" -Value $uninstall -Encoding ASCII Write-Host "uninstall.ps1 erzeugt." # 8. Optional: Autostart bei Anmeldung (mit Tray) +# +# Ueber den Autostart-ORDNER, nicht ueber schtasks: Eine Aufgabe im +# Wurzelordner der Aufgabenplanung anzulegen verlangt Administratorrechte, und +# der Installer laeuft normal ohne. Auf dem Commander-PC scheiterte das am +# 25.07.2026 mit "FEHLER: Zugriff verweigert." - und weil oben +# $ErrorActionPreference = "Stop" steht, riss es die ganze Installation mit, +# obwohl nur der Autostart fehlte. Der Autostart-Ordner braucht nie Adminrechte. if ($Autostart) { - schtasks /create /f /tn "RippyWorker" /tr "`"$ziel\start-tray.bat`"" /sc onlogon | Out-Null - Write-Host "Autostart-Aufgabe 'RippyWorker' registriert (Tray bei Anmeldung)." + try { + $autostartOrdner = [Environment]::GetFolderPath("Startup") + $wsh = New-Object -ComObject WScript.Shell + $lnk = $wsh.CreateShortcut((Join-Path $autostartOrdner "RippyWorker.lnk")) + $lnk.TargetPath = (Join-Path $ziel "start-tray.bat") + $lnk.WorkingDirectory = $ziel + $lnk.Description = "Rippy Encoding-Worker" + $lnk.Save() + Write-Host "Autostart eingerichtet (Verknuepfung im Autostart-Ordner)." + } catch { + Write-Host "HINWEIS: Autostart konnte nicht eingerichtet werden ($($_.Exception.Message))." -ForegroundColor Yellow + Write-Host " Der Worker ist trotzdem fertig installiert." -ForegroundColor Yellow + Write-Host " Von Hand: start-tray.bat in shell:startup verknuepfen." -ForegroundColor Yellow + } } Write-Host ""