HAMCTRL-installer.iss
Rama main · réplica de lectura del repositorio original.
; ============================================================================
; HAMCTRL-installer.iss — instalator HAM RADIO CTRL (Inno Setup)
; ============================================================================
; Buduje: HAMCTRL-Setup.exe
;
; WYMAGA: Inno Setup 6+ (https://jrsoftware.org/isdl.php)
;
; UZYCIE:
; 1. Zbuduj najpierw HAM-RADIO-CTRL.exe (py build_server.py)
; 2. Otworz ten plik w Inno Setup Compiler
; 3. Build -> Compile (albo F9)
; 4. Wynik: Output\HAMCTRL-Setup.exe
;
; Instalator:
; - instaluje HAM-RADIO-CTRL.exe do Program Files\HAM RADIO CTRL
; - tworzy skroty (pulpit + menu Start)
; - przy pierwszym uruchomieniu EXE otwiera przegladarke
; - dane usera (config, users, .env) ida do %APPDATA%\HAMCTRL
; (bo Program Files jest read-only - config.py to obsluguje)
; - deinstalator w Panelu sterowania
; ============================================================================
#define AppName "HAM RADIO CTRL"
; Trzymaj zgodne z VERSION (root repo) i SERVER_VERSION w webapp.py -
; wszystkie trzy bumpowane razem tylko przy release, nie przy kazdym commicie
; (to inny numer niz znacznik [build] BUILD-YYYY-MM-DD-... w logu startowym,
; ktory zmienia sie prawie na kazdy commit i sluzy do potwierdzenia ze EXE
; spakowal najnowszy kod - nie do publicznego wersjonowania).
#define AppVersion "2.0.17"
#define AppPublisher "Franek (Claude.ai) & SQ3MZM Tom"
#define AppExeName "HAM-RADIO-CTRL.exe"
#define AppURL "https://github.com/SQ3MZM/HAMCTRL"
[Setup]
; AppId: unikalny identyfikator (nie zmieniaj miedzy wersjami tego samego produktu)
AppId={{A7F3C2E1-8B4D-4E6A-9C1F-HAMCTRL000001}
AppName={#AppName}
AppVersion={#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
DefaultDirName={autopf}\HAM RADIO CTRL
DefaultGroupName=HAM RADIO CTRL
; Pozwol userowi wybrac katalog
DisableProgramGroupPage=yes
; Instalacja do Program Files wymaga admina
PrivilegesRequired=admin
OutputBaseFilename=HAMCTRL-Setup
OutputDir=Output
Compression=lzma2/max
SolidCompression=yes
WizardStyle=modern
; Ikona instalatora (icon.ico obok skryptu budowania)
SetupIconFile=icon.ico
; Minimalne wersje Windows (Win10+)
MinVersion=10.0
[Languages]
Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
; Auto-odnawianie certyfikatu Let's Encrypt co 60 dni (zalecane dla serwera
; dzialajacego 24/7 ze zdalnym dostepem). Domyslnie WLACZONE.
Name: "autocert"; Description: "Automatyczne odnawianie certyfikatu Let's Encrypt (co 60 dni, w tle)"; GroupDescription: "Zdalny dostep:"
[Files]
; Glowny EXE (spakowany serwer). Sciezka wzgledna - popraw jesli EXE gdzie indziej.
Source: "dist\{#AppExeName}"; DestDir: "{app}"; Flags: ignoreversion
; Opcjonalnie README/instrukcja dla klubu
; Source: "README-KLUB.txt"; DestDir: "{app}"; Flags: ignoreversion isreadme
[Icons]
; Menu Start
Name: "{group}\HAM RADIO CTRL"; Filename: "{app}\{#AppExeName}"
; Reset hasla admina (gdy klub zapomni) - uruchamia EXE z flaga
Name: "{group}\Reset hasla admina"; Filename: "{app}\{#AppExeName}"; Parameters: "--reset-admin"
; Generowanie certyfikatu Let's Encrypt - win-acme wymaga admina. EXE sam
; prosi o podniesienie uprawnien (UAC) przy --gen-cert, wiec wystarczy
; kliknac skrot i potwierdzic monit. Osobny skrot uruchamiany raz na ~90 dni.
; Serwer na co dzien dziala BEZ admina.
Name: "{group}\Wygeneruj certyfikat (jako admin)"; Filename: "{app}\{#AppExeName}"; Parameters: "--gen-cert"
Name: "{group}\Odinstaluj HAM RADIO CTRL"; Filename: "{uninstallexe}"
; Pulpit (opcjonalny - task desktopicon)
Name: "{autodesktop}\HAM RADIO CTRL"; Filename: "{app}\{#AppExeName}"; Tasks: desktopicon
[Run]
; Regula firewall (raz przy instalacji) - pozwala na nasluch portow serwera,
; zeby Defender nie pytal o dostep do sieci przy KAZDYM uruchomieniu.
; Obejmuje porty: 8000/8001 (HTTP/HTTPS), 9400-9444 (audio/FT8), 2238 (WSJT-X).
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall add rule name=""HAM RADIO CTRL"" dir=in action=allow program=""{app}\{#AppExeName}"" enable=yes profile=any"; Flags: runhidden waituntilterminated; StatusMsg: "Konfiguracja zapory sieciowej..."
; Osobna regula PORTOWA dla ham_audio.exe. Ten plik jest spakowany w bundlu
; PyInstaller i rozpakowywany przy KAZDYM starcie do losowej sciezki _MEIPASS,
; wiec regula "na program" nie zadziala (sciezka za kazdym razem inna) i zapora
; pytalaby w kolko. Regula na PORTY (9400 ctrl, 9401 WS audio, 9443 WSS audio)
; dziala niezaleznie od sciezki pliku. Port 9444 to polaczenie wychodzace do
; Pythona - nie wymaga reguly wejsciowej.
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall add rule name=""HAM RADIO CTRL Audio"" dir=in action=allow protocol=TCP localport=9400,9401,9443 enable=yes profile=any"; Flags: runhidden waituntilterminated; StatusMsg: "Konfiguracja zapory (audio)..."
; Zadanie w Harmonogramie: automatyczne odnawianie certyfikatu Let's Encrypt
; co 60 dni (cert wazny 90 dni - odnawiamy z zapasem). Uruchamia --gen-cert
; z najwyzszymi uprawnieniami (win-acme wymaga admina), w tle. Serwer sam
; podchwyci nowy cert przez hot-reload (bez restartu). PELNA bezobslugowosc.
; Uruchamiane tylko jesli user wybral zadanie autocert (domyslnie tak).
Filename: "{sys}\schtasks.exe"; Parameters: "/Create /TN ""HAMCTRL Cert Renewal"" /TR ""\""{app}\{#AppExeName}\"" --gen-cert"" /SC DAILY /MO 60 /RL HIGHEST /F /RU SYSTEM"; Flags: runhidden waituntilterminated; StatusMsg: "Konfiguracja auto-odnawiania certyfikatu..."; Tasks: autocert
; Auto-uruchomienie po instalacji USUNIETE celowo. Powodowalo blad 740
; (niezgodnosc kontekstu elevacji: instalator dziala jako admin, aplikacja
; jako asInvoker). Na roznych maszynach klubowych bylo zawodne. User uruchamia
; aplikacje ze skrotu w menu Start / na pulpicie - to dziala niezawodnie.
[UninstallRun]
; Przy deinstalacji usun zadanie odnawiania certu
Filename: "{sys}\schtasks.exe"; Parameters: "/Delete /TN ""HAMCTRL Cert Renewal"" /F"; Flags: runhidden; RunOnceId: "DelCertTask"
[UninstallRun]
; Przy deinstalacji usun regule firewall
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall delete rule name=""HAM RADIO CTRL"""; Flags: runhidden; RunOnceId: "DelFwRule"
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall delete rule name=""HAM RADIO CTRL Audio"""; Flags: runhidden; RunOnceId: "DelFwRuleAudio"
[UninstallDelete]
; Przy deinstalacji NIE usuwamy danych usera z APPDATA (konfiguracja, konta,
; logi QSO) - user moze chciec je zachowac. Jesli chcesz czyscic, odkomentuj:
; Type: filesandordirs; Name: "{userappdata}\HAMCTRL"
[Messages]
; Komunikat koncowy - kieruje usera do skrotu (auto-uruchomienie usuniete).
; FIX: this used to be ONE unscoped block, so it stayed in Polish even when
; the user picked "english" as the installer language - the [Languages]
; picker only translated Inno Setup's OWN stock wizard text, never this
; custom message. Split into [Messages.polish]/[Messages.english] sections
; so it actually follows the chosen language, same fix as the app's own
; startup language below.
[Messages.polish]
FinishedLabelNoIcons=Instalacja HAM RADIO CTRL zakonczona.%n%nUruchom aplikacje ze skrotu "HAM RADIO CTRL" w menu Start. Przy pierwszym uruchomieniu ustawisz haslo administratora, a nastepnie otworzy sie przegladarka z panelem.
FinishedLabel=Instalacja HAM RADIO CTRL zakonczona.%n%nUruchom aplikacje ze skrotu "HAM RADIO CTRL" w menu Start lub na pulpicie. Przy pierwszym uruchomieniu ustawisz haslo administratora, a nastepnie otworzy sie przegladarka z panelem.
[Messages.english]
FinishedLabelNoIcons=HAM RADIO CTRL installation complete.%n%nLaunch the app from the "HAM RADIO CTRL" shortcut in the Start menu. On first run you'll set the admin password, then a browser window with the panel will open.
FinishedLabel=HAM RADIO CTRL installation complete.%n%nLaunch the app from the "HAM RADIO CTRL" shortcut in the Start menu or on the desktop. On first run you'll set the admin password, then a browser window with the panel will open.
[Code]
function InitializeSetup(): Boolean;
begin
Result := True;
end;
// FIX: the app's UI always started in Polish regardless of which language
// was picked in this installer's own [Languages] picker - the picker only
// ever controlled the INSTALLER's wizard text, nothing carried the choice
// through to the app itself. This writes a small marker file that
// data.py::get_cfg() reads ONCE, on the app's very first start (before
// config.json exists), to seed the server-wide default UI language - see
// the matching comment there and in index.html's inline bootstrap script.
procedure CurStepChanged(CurStep: TSetupStep);
var
LangCode: String;
MarkerDir: String;
MarkerFile: String;
RuntimeDir: String;
begin
if CurStep = ssPostInstall then
begin
if ActiveLanguage() = 'polish' then
LangCode := 'pl'
else
LangCode := 'en';
MarkerDir := ExpandConstant('{userappdata}\HAMCTRL');
ForceDirectories(MarkerDir);
MarkerFile := MarkerDir + '\install_lang.txt';
SaveStringToFile(MarkerFile, LangCode, False);
// FIX (2026-10-20, live report: new favicon.ico shipped in a new EXE
// build never appeared on a running server - [static] MISSING FILE in
// the log despite the console confirming the latest [build] marker).
// hamctrl.spec uses a PERSISTENT PyInstaller onefile extraction folder
// (runtime_tmpdir=%APPDATA%\HAMCTRL\_runtime, see its own comment there)
// instead of a fresh %TEMP%\_MEIxxxxxx each run, specifically so a 24/7
// server's files survive Windows' temp-cleanup. The flip side: on an
// UPGRADE, a stale extraction from the OLD build can stick around and
// the new EXE doesn't necessarily get a fully fresh folder. Clearing
// this cache on every install/update forces a clean re-extraction on
// next launch - safe, it holds zero user data (config.json/users.json/
// qso.db live directly under %APPDATA%\HAMCTRL, untouched by this).
RuntimeDir := ExpandConstant('{userappdata}\HAMCTRL\_runtime');
if DirExists(RuntimeDir) then
DelTree(RuntimeDir, True, True, True);
end;
end;
// Przy DEINSTALACJI pytamy czy usunac dane uzytkownika (konta, konfiguracja,
// logi QSO w %APPDATA%\HAMCTRL). Domyslnie NIE - zeby reinstalacja/aktualizacja
// nie kasowala kont. User moze wybrac pelne czyszczenie.
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
DataDir: String;
begin
if CurUninstallStep = usUninstall then
begin
DataDir := ExpandConstant('{userappdata}\HAMCTRL');
if DirExists(DataDir) then
begin
if MsgBox('Czy usunac takze dane uzytkownika?' + #13#10 + #13#10 +
'Obejmuje: konta i hasla, konfiguracje radia, logi QSO.' + #13#10 +
'Lokalizacja: ' + DataDir + #13#10 + #13#10 +
'TAK = pelne czyszczenie (wszystko znika)' + #13#10 +
'NIE = zachowaj dane (przydatne przy reinstalacji)',
mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then
begin
DelTree(DataDir, True, True, True);
end;
end;
end;
end;