added install wizard
This commit is contained in:
@@ -77,13 +77,44 @@ dotnet run --project src/EbbesMemeClipboard
|
|||||||
# build
|
# build
|
||||||
dotnet build
|
dotnet build
|
||||||
|
|
||||||
# publish self-contained single-file binary -> publish/EbbesMemeClipboard.exe (~78 MB)
|
# portable single exe -> publish/EbbesMemeClipboard.exe (~75 MB, compressed)
|
||||||
dotnet publish src/EbbesMemeClipboard/EbbesMemeClipboard.csproj -c Release -r win-x64 \
|
dotnet publish src/EbbesMemeClipboard/EbbesMemeClipboard.csproj -c Release -r win-x64 \
|
||||||
--self-contained true -p:PublishSingleFile=true \
|
--self-contained true -p:PublishSingleFile=true \
|
||||||
-p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=true \
|
-p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=true \
|
||||||
-o publish
|
-o publish
|
||||||
|
|
||||||
|
# installer build: NOTE compression deliberately OFF (see below) -> publish-installer/ (~172 MB)
|
||||||
|
dotnet publish src/EbbesMemeClipboard/EbbesMemeClipboard.csproj -c Release -r win-x64 \
|
||||||
|
--self-contained true -p:PublishSingleFile=true \
|
||||||
|
-p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=false \
|
||||||
|
-o publish-installer
|
||||||
|
|
||||||
|
# then compile the wizard -> installer/output/EbbesMemeClipboard-Setup-<version>.exe (~51 MB)
|
||||||
|
"$LOCALAPPDATA/Programs/Inno Setup 6/ISCC.exe" installer/EbbesMemeClipboard.iss
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Installer (Inno Setup)
|
||||||
|
|
||||||
|
Script: `installer/EbbesMemeClipboard.iss` (tracked; `installer/output/` is gitignored).
|
||||||
|
Inno Setup 6 installs **per-user** to `%LocalAppData%\Programs\Inno Setup 6\`, not Program
|
||||||
|
Files — that tripped up the first attempt to locate `ISCC.exe`.
|
||||||
|
|
||||||
|
- Per-user install by default (no UAC), with a wizard page letting the user pick
|
||||||
|
"just me" vs "all users" (`PrivilegesRequired=lowest` +
|
||||||
|
`PrivilegesRequiredOverridesAllowed=dialog`).
|
||||||
|
- Optional unchecked tasks: desktop icon, start-with-Windows.
|
||||||
|
- **Don't double-compress.** Publishing with `EnableCompressionInSingleFile=false` and
|
||||||
|
letting Inno's LZMA2 do the work gives a ~51 MB setup vs ~70 MB, and the installed app
|
||||||
|
starts faster because there's no decompression at launch.
|
||||||
|
- **Uninstall only removes the autostart entry if it points at the installed copy.** The
|
||||||
|
app's own Settings toggle writes the same `Run` value name, so an unconditional delete
|
||||||
|
would wipe out a portable build's autostart. This was a real bug caught in testing.
|
||||||
|
- User data under `%AppData%\EbbesMemeClipboard` is deliberately preserved on uninstall;
|
||||||
|
only the re-downloadable `GifCache` is removed.
|
||||||
|
- Verified end-to-end: silent install → files/shortcut/uninstall-entry present → app runs →
|
||||||
|
silent uninstall → everything removed, user data and unrelated autostart intact.
|
||||||
|
- An installer does **not** fix SmartScreen warnings; only code signing does.
|
||||||
|
|
||||||
Note: the published single-file exe takes **~10 seconds on first launch** before the tray
|
Note: the published single-file exe takes **~10 seconds on first launch** before the tray
|
||||||
icon appears (native library self-extraction to TEMP). Not a bug. Subsequent launches are
|
icon appears (native library self-extraction to TEMP). Not a bug. Subsequent launches are
|
||||||
faster.
|
faster.
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
; Inno Setup script for Ebbe's Meme Clipboard.
|
||||||
|
;
|
||||||
|
; Build with:
|
||||||
|
; "%LocalAppData%\Programs\Inno Setup 6\ISCC.exe" installer\EbbesMemeClipboard.iss
|
||||||
|
;
|
||||||
|
; Expects an installer-flavoured publish first (note: compression DISABLED on purpose):
|
||||||
|
; dotnet publish src\EbbesMemeClipboard\EbbesMemeClipboard.csproj -c Release -r win-x64 ^
|
||||||
|
; --self-contained true -p:PublishSingleFile=true ^
|
||||||
|
; -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=false ^
|
||||||
|
; -o publish-installer
|
||||||
|
;
|
||||||
|
; Leaving .NET's own single-file compression off lets Inno's LZMA2 compress the raw bytes
|
||||||
|
; instead, which it does far better: ~51 MB setup vs ~70 MB when double-compressing. The
|
||||||
|
; installed exe is larger on disk (172 MB vs 75 MB) but starts faster, since there's no
|
||||||
|
; decompression on launch. The separate publish\ folder keeps the compressed build for
|
||||||
|
; anyone who just wants the portable single exe.
|
||||||
|
|
||||||
|
#define AppName "Ebbe's Meme Clipboard"
|
||||||
|
#define AppVersion "1.1.0"
|
||||||
|
#define AppPublisher "Ebbe Baß"
|
||||||
|
#define AppExeName "EbbesMemeClipboard.exe"
|
||||||
|
#define SourceExe "..\publish-installer\EbbesMemeClipboard.exe"
|
||||||
|
|
||||||
|
[Setup]
|
||||||
|
AppId={{8E4C1F02-6B3A-4D77-9C21-5A0E7F3B9D64}
|
||||||
|
AppName={#AppName}
|
||||||
|
AppVersion={#AppVersion}
|
||||||
|
AppVerName={#AppName} {#AppVersion}
|
||||||
|
AppPublisher={#AppPublisher}
|
||||||
|
DefaultDirName={autopf}\Ebbes Meme Clipboard
|
||||||
|
DefaultGroupName={#AppName}
|
||||||
|
UninstallDisplayName={#AppName}
|
||||||
|
UninstallDisplayIcon={app}\{#AppExeName}
|
||||||
|
OutputDir=.\output
|
||||||
|
OutputBaseFilename=EbbesMemeClipboard-Setup-{#AppVersion}
|
||||||
|
SetupIconFile=..\src\EbbesMemeClipboard\Assets\tray-icon.ico
|
||||||
|
Compression=lzma2/max
|
||||||
|
SolidCompression=yes
|
||||||
|
WizardStyle=modern
|
||||||
|
DisableProgramGroupPage=yes
|
||||||
|
ArchitecturesAllowed=x64compatible
|
||||||
|
ArchitecturesInstallIn64BitMode=x64compatible
|
||||||
|
|
||||||
|
; Default to a per-user install so no UAC prompt is needed, but show a dialog letting the
|
||||||
|
; user pick "just me" or "all users". {autopf} then resolves to LocalAppData\Programs or
|
||||||
|
; Program Files to match whichever they chose.
|
||||||
|
PrivilegesRequired=lowest
|
||||||
|
PrivilegesRequiredOverridesAllowed=dialog
|
||||||
|
|
||||||
|
; The app has no single-instance mutex, so a running copy would hold a lock on the exe and
|
||||||
|
; break an upgrade. Restart Manager closes it first and reopens it afterwards.
|
||||||
|
CloseApplications=yes
|
||||||
|
RestartApplications=yes
|
||||||
|
|
||||||
|
[Languages]
|
||||||
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
|
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
||||||
|
|
||||||
|
[Tasks]
|
||||||
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||||
|
Name: "autostart"; Description: "Start {#AppName} when Windows starts"; GroupDescription: "Startup:"; Flags: unchecked
|
||||||
|
|
||||||
|
[Files]
|
||||||
|
Source: "{#SourceExe}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"
|
||||||
|
Name: "{group}\{cm:UninstallProgram,{#AppName}}"; Filename: "{uninstallexe}"
|
||||||
|
Name: "{autodesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desktopicon
|
||||||
|
|
||||||
|
[Registry]
|
||||||
|
; Same value name the app's own Settings toggle manages, so the installer checkbox and the
|
||||||
|
; in-app checkbox stay in agreement instead of fighting over two separate entries.
|
||||||
|
Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; \
|
||||||
|
ValueName: "EbbesMemeClipboard"; ValueData: """{app}\{#AppExeName}"""; \
|
||||||
|
Flags: uninsdeletevalue; Tasks: autostart
|
||||||
|
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#AppName}}"; \
|
||||||
|
Flags: nowait postinstall skipifsilent
|
||||||
|
|
||||||
|
[UninstallDelete]
|
||||||
|
; The app writes its library/settings under %AppData% and a re-downloadable cache under
|
||||||
|
; %LocalAppData%. Only the cache is removed automatically - the user's own memes, favourites
|
||||||
|
; and settings are deliberately left behind so an uninstall/reinstall doesn't destroy them.
|
||||||
|
Type: filesandordirs; Name: "{localappdata}\EbbesMemeClipboard\GifCache"
|
||||||
|
|
||||||
|
[Code]
|
||||||
|
// Clean up the autostart entry on uninstall, but ONLY when it actually points at the copy
|
||||||
|
// being removed. The app's own Settings toggle writes the same value name, so a user running
|
||||||
|
// a portable build alongside this one would otherwise have their autostart silently deleted
|
||||||
|
// by an uninstall that had nothing to do with it.
|
||||||
|
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||||
|
var
|
||||||
|
Existing: String;
|
||||||
|
AppPath: String;
|
||||||
|
begin
|
||||||
|
if CurUninstallStep <> usPostUninstall then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
if not RegQueryStringValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Run',
|
||||||
|
'EbbesMemeClipboard', Existing) then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
AppPath := LowerCase(ExpandConstant('{app}'));
|
||||||
|
if Pos(AppPath, LowerCase(Existing)) > 0 then
|
||||||
|
RegDeleteValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Run', 'EbbesMemeClipboard');
|
||||||
|
end;
|
||||||
Reference in New Issue
Block a user