diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ee0cf36..1de21ff 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,12 @@ # AstroProject Forge — note di rilascio +## 1.0.3 — 28 luglio 2026 + +- Le nuove installazioni Windows usano `C:\Program Files\AstroProject Forge`. +- L'installer mantiene lo stesso identificatore e aggiorna direttamente la copia esistente. +- Le vecchie installazioni per utente vengono migrate dalla cartella `%LOCALAPPDATA%\Programs` senza toccare impostazioni, progetti o immagini. +- Gli aggiornamenti richiedono soltanto la conferma UAC di Windows; installazione e riavvio proseguono automaticamente. + ## 1.0.2 — 28 luglio 2026 - Mostra una conferma discreta dopo il riavvio automatico, così è immediatamente visibile che l'aggiornamento è riuscito. diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md index 5861ef5..6438bee 100644 --- a/docs/RELEASE_PROCESS.md +++ b/docs/RELEASE_PROCESS.md @@ -29,3 +29,5 @@ The `Cross-platform parity QA` GitHub workflow builds: Create a non-draft, non-prerelease tag matching the version, then attach only installable and portable packages. GitHub adds the source archives automatically. The Windows updater reads the latest stable GitHub release, checks the published asset size and SHA-256 digest, downloads it into the local application data folder, runs the installer silently and restarts the newly installed version. The About window also keeps a separate manual-download link. + +Stable Windows installations use `C:\Program Files\AstroProject Forge`. The stable Inno Setup AppId must never change: it identifies an existing installation during upgrades. Releases from 1.0.3 also remove the exact legacy per-user application directory after migration, while preserving settings and projects under local application data. diff --git a/installer/AstroProjectForge.iss b/installer/AstroProjectForge.iss index 99d2a50..dba85fa 100644 --- a/installer/AstroProjectForge.iss +++ b/installer/AstroProjectForge.iss @@ -29,11 +29,13 @@ AppVersion={#MyAppVersion} AppVerName=AstroProject Forge{#ChannelSuffix} {#MyAppVersion} AppPublisher=Gianmarco Spagnoli AppPublisherURL=https://github.com/astropuzzo/astroproject-forge -DefaultDirName={localappdata}\Programs\AstroProject Forge{#ChannelSuffix} +DefaultDirName={autopf}\AstroProject Forge{#ChannelSuffix} DefaultGroupName=AstroProject Forge{#ChannelSuffix} -PrivilegesRequired=lowest +PrivilegesRequired=admin ArchitecturesAllowed=x64compatible +ArchitecturesInstallIn64BitMode=x64compatible SetupArchitecture=x64 +UsePreviousAppDir=no OutputDir={#OutputDir} OutputBaseFilename=AstroProjectForge-{#MyChannel}-{#MyAppVersion}-win-x64-setup SetupIconFile=..\assets\astroforge.ico @@ -64,7 +66,7 @@ Source: "{#SourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs [Icons] Name: "{group}\AstroProject Forge{#ChannelSuffix}"; Filename: "{app}\AstroForge.App.exe" -Name: "{autodesktop}\AstroProject Forge{#ChannelSuffix}"; Filename: "{app}\AstroForge.App.exe"; Tasks: desktopicon +Name: "{autodesktop}\AstroProject Forge{#ChannelSuffix}"; Filename: "{app}\AstroForge.App.exe"; Check: ShouldCreateDesktopIcon [Run] ; Manual installs keep the familiar optional launch checkbox. @@ -73,17 +75,112 @@ Filename: "{app}\AstroForge.App.exe"; Description: "Avvia AstroProject Forge{#Ch Filename: "{app}\AstroForge.App.exe"; Parameters: "--updated"; Flags: nowait; Check: IsAutomaticUpdate [Registry] -Root: HKCU; Subkey: "Software\Classes\.astroforge"; ValueType: string; ValueData: "AstroProjectForge.Project"; Flags: uninsdeletevalue -Root: HKCU; Subkey: "Software\Classes\AstroProjectForge.Project"; ValueType: string; ValueData: "Progetto AstroProject Forge"; Flags: uninsdeletekey -Root: HKCU; Subkey: "Software\Classes\AstroProjectForge.Project\DefaultIcon"; ValueType: string; ValueData: "{app}\AstroForge.App.exe,0" -Root: HKCU; Subkey: "Software\Classes\AstroProjectForge.Project\shell\open\command"; ValueType: string; ValueData: """{app}\AstroForge.App.exe"" ""%1""" +Root: HKA; Subkey: "Software\Classes\.astroforge"; ValueType: string; ValueData: "AstroProjectForge.Project"; Flags: uninsdeletevalue +Root: HKA; Subkey: "Software\Classes\AstroProjectForge.Project"; ValueType: string; ValueData: "Progetto AstroProject Forge"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\AstroProjectForge.Project\DefaultIcon"; ValueType: string; ValueData: "{app}\AstroForge.App.exe,0" +Root: HKA; Subkey: "Software\Classes\AstroProjectForge.Project\shell\open\command"; ValueType: string; ValueData: """{app}\AstroForge.App.exe"" ""%1""" [Code] +var + LegacyInstallDirectories: TArrayOfString; + LegacyUninstallRegistryKeys: TArrayOfString; + +function LegacyUninstallId(): String; +begin +#if MyChannel == "Stable" + Result := '{C415EAC5-5B2C-4DB1-B349-1A70BB894F38}_is1'; +#else + Result := '{BD5A66C8-8858-48EE-A36E-659D809D5549}_is1'; +#endif +end; + +function IsExactLegacyInstallPath(Value: String): Boolean; +var + NormalizedValue: String; + RequiredSuffix: String; +begin + NormalizedValue := RemoveBackslashUnlessRoot(ExpandFileName(Value)); + RequiredSuffix := '\AppData\Local\Programs\AstroProject Forge{#ChannelSuffix}'; + Result := + (Length(NormalizedValue) > Length(RequiredSuffix)) and + (CompareText( + Copy(NormalizedValue, Length(NormalizedValue) - Length(RequiredSuffix) + 1, Length(RequiredSuffix)), + RequiredSuffix) = 0) and + FileExists(AddBackslash(NormalizedValue) + 'AstroForge.App.exe'); +end; + +procedure DiscoverLegacyInstalls(); +var + UserSids: TArrayOfString; + Index: Integer; + Count: Integer; + RegistryKey: String; + InstallDirectory: String; +begin + if not RegGetSubkeyNames(HKU, '', UserSids) then + Exit; + + for Index := 0 to GetArrayLength(UserSids) - 1 do + begin + RegistryKey := + UserSids[Index] + + '\Software\Microsoft\Windows\CurrentVersion\Uninstall\' + + LegacyUninstallId(); + if + RegQueryStringValue(HKU, RegistryKey, 'InstallLocation', InstallDirectory) and + IsExactLegacyInstallPath(InstallDirectory) + then + begin + Count := GetArrayLength(LegacyInstallDirectories); + SetArrayLength(LegacyInstallDirectories, Count + 1); + SetArrayLength(LegacyUninstallRegistryKeys, Count + 1); + LegacyInstallDirectories[Count] := RemoveBackslashUnlessRoot(ExpandFileName(InstallDirectory)); + LegacyUninstallRegistryKeys[Count] := RegistryKey; + end; + end; +end; + +function InitializeSetup(): Boolean; +begin + DiscoverLegacyInstalls(); + Result := True; +end; + +function ShouldCreateDesktopIcon(): Boolean; +begin + Result := + WizardIsTaskSelected('desktopicon') or + FileExists(ExpandConstant('{autodesktop}\AstroProject Forge{#ChannelSuffix}.lnk')); +end; + function IsAutomaticUpdate(): Boolean; begin Result := CompareText(ExpandConstant('{param:APFUPDATE|0}'), '1') = 0; end; +procedure RegisterExtraCloseApplicationsResources(); +var + Index: Integer; +begin + for Index := 0 to GetArrayLength(LegacyInstallDirectories) - 1 do + RegisterExtraCloseApplicationsResource( + AddBackslash(LegacyInstallDirectories[Index]) + 'AstroForge.App.exe'); +end; + +procedure CurStepChanged(CurStep: TSetupStep); +var + Index: Integer; +begin + if CurStep = ssPostInstall then + begin + for Index := 0 to GetArrayLength(LegacyInstallDirectories) - 1 do + DelTree(LegacyInstallDirectories[Index], True, True, True); + + for Index := 0 to GetArrayLength(LegacyUninstallRegistryKeys) - 1 do + RegDeleteKeyIncludingSubkeys(HKU, LegacyUninstallRegistryKeys[Index]); + end; +end; + function InitializeUninstall(): Boolean; var Choice: Integer; diff --git a/version.json b/version.json index 85a8b2e..06db03e 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { - "version": "1.0.2", + "version": "1.0.3", "channel": "Stable", "releaseDate": "2026-07-28", "minimumWindowsBuild": 19045