65edf8369e
Ampel / ampel (push) Successful in 28s
Commander-Wunsch: nicht ins Benutzerprofil, sondern wie jedes andere Programm
nach C:\Program Files - und selbst waehlbar, mit diesem Standard.
## Was neu ist
- Feld "Installieren nach" mit Knopf "Aendern ..." (Ordner-Dialog). Standard
ist [Environment]::GetFolderPath("ProgramFiles") + "Rippy Worker" - der
ECHTE Pfad; deutsche Windows-Versionen zeigen im Explorer "Programme", der
Pfad heisst trotzdem "Program Files".
- Der Ordner-Dialog liefert den ELTERN-Ordner, "Rippy Worker" haengt der
Installer selbst an. Sonst koennte die Deinstallation einen fremden Ordner
mitloeschen - sie macht Remove-Item -Recurse auf das Zielverzeichnis.
- install.ps1 bekommt -InstallDir mit demselben Standard.
## Drei Folgen, die mitbehandelt werden mussten
1. RECHTE. In C:\Program Files darf nur ein Administrator schreiben. Die .exe
traegt jetzt ein requireAdministrator-Manifest (-requireAdmin in
build-exe.ps1), fragt also beim Doppelklick EINMAL per UAC - danach stimmen
die Rechte fuer alles Weitere. Verifiziert: "requireAdministrator" steckt im
Manifest, "asInvoker" nicht mehr. Zusaetzlich prueft der Installer VOR dem
Entpacken, ob er dort schreiben darf, und nennt bei Nein die zwei Wege
(als Administrator starten ODER Ziel ins eigene Profil legen) - statt
irgendwo tief "Zugriff verweigert" zu produzieren.
2. DAS LOG. tray.py schrieb worker.log NEBEN das Programm. Unter Program Files
darf ein normaler Benutzer das nicht - der Worker waere beim Starten
gescheitert, und zwar still. Das Log liegt jetzt in
%LOCALAPPDATA%\Rippy Worker\worker.log, also da, wo veraenderliche Daten
hingehoeren. Rueckfall auf das Programmverzeichnis bleibt fuer
Installationen ins eigene Profil.
3. DER AUTOSTART. Bei einer Installation unter Programme ist es eine
Installation FUER DIE MASCHINE - der Autostart geht deshalb in den
Autostart-Ordner aller Benutzer (CommonStartup). Das loest zugleich ein
Rechte-Problem: erhoeht man ueber ein FREMDES Administratorkonto, waere
GetFolderPath("Startup") der Ordner dieses Admins, also der falsche. Bei
einem Ziel im eigenen Profil bleibt es persoenlich. uninstall.ps1 raeumt
beide Orte ab.
## Geprueft
- Leerzeichen im Pfad: die erzeugte .bat mit cd /d "%~dp0", PATH-Erweiterung
und relativem Aufruf laeuft aus "C:\...\Rippy Test Ordner" korrekt durch.
- Alle drei .ps1 ASCII-rein und fehlerfrei geparst.
- RippyWorkerSetup.exe neu gebaut (52736 -> 57344 Bytes, Version 1.0.1.0).
UI: Der Copy-Paste-Befehl fuer den CLI-Weg sagt jetzt, dass PowerShell als
Administrator laufen muss, und nennt -InstallDir als Ausweg ohne Adminrechte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
69 lines
3.7 KiB
PowerShell
69 lines
3.7 KiB
PowerShell
# 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)
|
|
#
|
|
# -requireAdmin (seit 25.07.2026): Der Worker wird standardmaessig nach
|
|
# "C:\Program Files\Rippy Worker" installiert, und dorthin darf nur ein
|
|
# Administrator schreiben. Mit dem Schalter tragt die .exe ein Manifest, das
|
|
# Windows beim Doppelklick EINMAL per UAC fragen laesst - danach stimmen die
|
|
# Rechte fuer alles Weitere. Ohne ihn liefe der Installer unerhoeht und
|
|
# scheiterte beim Anlegen des Ordners; wer das Ziel ins eigene Profil legt,
|
|
# braucht die Erhoehung nicht, wird aber trotzdem gefragt (normal fuer einen
|
|
# Installer und besser als ein Fehlschlag mitten im Lauf).
|
|
Invoke-ps2exe -inputFile $guiSrc -outputFile "$PSScriptRoot\RippyWorkerSetup.exe" `
|
|
-iconFile "$PSScriptRoot\rippy.ico" -noConsole -STA -requireAdmin `
|
|
-title "Rippy Worker Setup" -product "Rippy" -company "Rippy" -version "1.0.1.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"
|
|
}
|