Further Install Refinements

Add Config Migration
Add Legacy Install Uninstaller
Improve Pre and Post Un/install status display
Install to PF32
Add Support and Publisher URL
Remove Registry section
This commit is contained in:
Stewart Cossey
2021-02-23 21:36:48 +13:00
parent 0b00acafdd
commit 70f7e29a6e
3 changed files with 161 additions and 13 deletions

View File

@@ -3,8 +3,9 @@
#define PRODUCT_VERSION "5.6"
#define COMPANY "Technitium"
#define TITLE "Technitium DNS Server"
#define APP_URL "https://technitium.com/dns/"
#define FILES_LOCATION "..\..\DnsService\bin\Release"
#define FILES_LOCATION "..\..\DnsService\bin\Release\net5.0-windows7.0"
#define TRAYAPP_LOCATION "..\..\DnsServerSystemTrayApp\obj\Release"
#define TRAYAPP_FILENAME "DnsServerSystemTrayApp.exe"
@@ -12,18 +13,25 @@
#define SERVICE_FILE "DnsService.exe"
#define SERVICE_DISPLAY_NAME "Technitium DNS Server"
#define SERVICE_DESCRIPTION "Technitium DNS Server"
#define CONFIG_FOLDER "{app}\config"
#define CONFIG_FOLDER_COMPANY "{localappdata}\Technitium"
#define CONFIG_FOLDER_FULL CONFIG_FOLDER_COMPANY + "\DNS Server"
#define LEGACY_INSTALLER_APPID "{9B86AC7F-53B3-4E31-B245-D4602D16F5C8}"
#define LEGACY_INSTALLER_CONFIG_PATH "{commonpf32}\Technitium\DNS Server\config"
[Setup]
PrivilegesRequired=admin
AppName={#TITLE}
AppVersion={#PRODUCT_VERSION}
AppId={#APPID}
DefaultDirName={commonpf}\{#COMPANY}\{#PRODUCT_NAME}
DefaultDirName={commonpf32}\{#COMPANY}\{#PRODUCT_NAME}
DefaultGroupName={#COMPANY}
DisableProgramGroupPage=yes
AppCopyright=Copyright (c) 2021 {#COMPANY}
AppPublisher={#COMPANY}
AppSupportURL={#APP_URL}
AppPublisherURL={#APP_URL}
OutputDir=..\Release
OutputBaseFilename=DnsServiceSetup
CloseApplications=no
@@ -33,7 +41,7 @@ WizardSmallImageFile=logo.bmp
[Files]
Source: "{#TRAYAPP_LOCATION}\{#TRAYAPP_FILENAME}"; DestDir: "{app}";
Source: "{#FILES_LOCATION}\*.*"; Excludes: "*.pdb"; DestDir: "{app}"; Flags: recursesubdirs;
Source: "{#FILES_LOCATION}\*.*"; Excludes: "*.pdb,*.runtimeconfig.dev.json"; DestDir: "{app}"; Flags: recursesubdirs;
[Tasks]
Name: "desktopicon"; Description: "Create an icon on the &desktop";
@@ -45,16 +53,12 @@ ServiceInstallFailure=The DNS Service could not be installed. %1
ServiceManagerUnavailable=The Service Manager is not available!
DependenciesDir=.
[Registry]
Root: HKLM; Subkey: "Software\{#COMPANY}"; Flags: uninsdeletekeyifempty
Root: HKCU; Subkey: "Software\{#COMPANY}"; Flags: uninsdeletekeyifempty
[Icons]
Name: "{userprograms}\Technitium DNS Server"; Comment: "DNS Server Tray App"; Filename: "{app}\DnsServerSystemTrayApp.exe"; WorkingDir: "{app}\"; Flags: createonlyiffileexists
Name: "{userdesktop}\Technitium DNS Server"; Filename: "{app}\DnsServerSystemTrayApp.exe"; WorkingDir: "{app}\"; Flags: createonlyiffileexists; Tasks: desktopicon
[Run]
Filename: "{app}\DnsServerSystemTrayApp.exe"; Description: "Run the Tray App"; Flags: postinstall nowait
Filename: "{app}\DnsServerSystemTrayApp.exe"; Description: "Run the Tray App"; Flags: postinstall nowait;
;Include the dependency code
#include "depend\lang\english.iss"

View File

@@ -12,6 +12,23 @@ begin
RegQueryStringValue(HKCU, UninstallKey, 'UninstallString', Value)) and (Value <> '');
end;
function IsLegacyInstallerInstalled: Boolean;
var
Value: string;
UninstallKey: string;
begin
UninstallKey := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#LEGACY_INSTALLER_APPID}';
Result := (RegQueryStringValue(HKLM, UninstallKey, 'UninstallString', Value) or
RegQueryStringValue(HKCU, UninstallKey, 'UninstallString', Value)) and (Value <> '');
end;
function IsLegacyConfigAvailable: Boolean;
var
Value: string;
begin
Result := DirExists(ExpandConstant('{#LEGACY_INSTALLER_CONFIG_PATH}'));
end;
//Skips the Task selection screen if an upgrade install
function ShouldSkipPage(PageID: Integer): Boolean;
begin
@@ -22,6 +39,15 @@ function InitializeSetup(): boolean;
begin
//Specify the dependencies to install here
dotnet_5_desktop();
if IsLegacyInstallerInstalled or IsLegacyConfigAvailable then begin
AdditionalMemo := AdditionalMemo + #13#10 + #13#10 + 'Previous Version:';
end;
if IsLegacyInstallerInstalled then begin
AdditionalMemo := AdditionalMemo + #13#10 + ' Remove Legacy Installer';
end;
if IsLegacyConfigAvailable then begin
AdditionalMemo := AdditionalMemo + #13#10 + ' Migrate Configuration';
end;
Result := true;
end;
@@ -32,6 +58,14 @@ begin
Exec(ExpandConstant('taskkill.exe'), '/f /im ' + '"' + fileName + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
function MsiExecUnins(appId: String): Integer;
var
ResultCode: Integer;
begin
ShellExec('', 'msiexec.exe', '/x ' + appId + ' /qn', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
Result := ResultCode;
end;
procedure KillTrayApp; //Kill the tray app. Inno Setup cannot seem to close it through the "Close Applications" dialog.
begin
TaskKill('{#TRAYAPP_FILENAME}');
@@ -147,19 +181,109 @@ begin
end;
end;
procedure UninstallLegacyInstaller;
var
ResultCode: Integer;
begin
if IsLegacyInstallerInstalled then begin
Log('Uninstall MSI installer item');
ResultCode := MsiExecUnins('{#LEGACY_INSTALLER_APPID}');
Log('Result code ' + IntToStr(ResultCode));
end;
end;
procedure RemoveConfiguration(); //Removes the configuration left by the DNS Server
var
DeleteSuccess: Boolean;
begin
Log('Delete configuration folder');
DeleteSuccess := DelTree(ExpandConstant('{#CONFIG_FOLDER}'), True, True, True);
DeleteSuccess := DelTree(ExpandConstant('{#CONFIG_FOLDER_FULL}'), True, True, True);
if not DeleteSuccess then
begin
Log('Not all configuration files were deleted succesfully in ' + ExpandConstant('{#CONFIG_FOLDER}'));
Log('Not all configuration files were deleted succesfully in ' + ExpandConstant('{#CONFIG_FOLDER_FULL}'));
SuppressibleMsgBox(ExpandConstant('{cm:RemoveConfigFail}'), mbError, MB_OK, IDOK);
end;
end;
procedure DirectoryCopy(SourcePath, DestPath: string);
var
FindRec: TFindRec;
SourceFilePath: string;
DestFilePath: string;
begin
if FindFirst(SourcePath + '\*', FindRec) then
begin
try
repeat
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
begin
SourceFilePath := SourcePath + '\' + FindRec.Name;
DestFilePath := DestPath + '\' + FindRec.Name;
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin
if FileCopy(SourceFilePath, DestFilePath, False) then
begin
Log(Format('Copied %s to %s', [SourceFilePath, DestFilePath]));
end
else
begin
Log(Format('Failed to copy %s to %s', [SourceFilePath, DestFilePath]));
end;
end
else
begin
if DirExists(DestFilePath) or CreateDir(DestFilePath) then
begin
Log(Format('Created %s', [DestFilePath]));
DirectoryCopy(SourceFilePath, DestFilePath);
end
else
begin
Log(Format('Failed to create %s', [DestFilePath]));
end;
end;
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end
else
begin
Log(Format('Failed to list %s', [SourcePath]));
end;
end;
procedure MigrateConfiguration();
var
ConfigDirExists : Boolean;
begin
if IsLegacyConfigAvailable then begin
Log('Begin Configuration Migration');
ConfigDirExists := DirExists(ExpandConstant('{#CONFIG_FOLDER_COMPANY}'));
if not ConfigDirExists then begin
Log('Create config folder company');
CreateDir(ExpandConstant('{#CONFIG_FOLDER_COMPANY}'));
end;
ConfigDirExists := DirExists(ExpandConstant('{#CONFIG_FOLDER_FULL}'));
if not ConfigDirExists then begin
Log('Create config folder program');
CreateDir(ExpandConstant('{#CONFIG_FOLDER_FULL}'));
end;
DirectoryCopy(ExpandConstant('{#LEGACY_INSTALLER_CONFIG_PATH}'), ExpandConstant('{#CONFIG_FOLDER_FULL}'));
DelTree(ExpandConstant('{#LEGACY_INSTALLER_CONFIG_PATH}'), true, true, true);
Log('Complete Configuration Migration');
end;
end;
procedure PromptRemoveConfiguration(); //Asks users if they want their config removed. On unattended installs, will keep config unless /removeconfig=true is supplied
begin
case ExpandConstant('{param:removeconfig|prompt}') of
@@ -176,11 +300,26 @@ end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssInstall then begin //Step happens just before installing files
WizardForm.StatusLabel.Caption := 'Stopping Tray App...';
KillTrayApp(); //Stop the tray app if running
DoRemoveService(); //Stop and remove the service if installed
if IsLegacyInstallerInstalled or IsLegacyConfigAvailable then begin
WizardForm.StatusLabel.Caption := 'Stopping Service...';
DoStopService(); //Stop the service if running
WizardForm.StatusLabel.Caption := 'Removing Legacy Installer...';
UninstallLegacyInstaller(); //Uninstall Legacy Installer if Installed already
WizardForm.StatusLabel.Caption := 'Migrating Configuration...';
MigrateConfiguration(); //Shift configuration into correct path
end else begin
WizardForm.StatusLabel.Caption := 'Uninstalling Service...';
DoRemoveService(); //Stop and remove the service if installed
end;
end;
if CurStep = ssPostInstall then begin //Step happens just after installing files
DoInstallService(); //Install service after all files installed
WizardForm.StatusLabel.Caption := 'Installing Service...';
DoInstallService(); //Install service after all files installed, if not a portable install
end;
end;
@@ -188,7 +327,9 @@ procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then //Step happens before processing uninstall log
begin
UninstallProgressForm.StatusLabel.Caption := 'Stopping Tray App...';
KillTrayApp(); //Stop the tray app if running
UninstallProgressForm.StatusLabel.Caption := 'Uninstalling Service...';
DoRemoveService(); //Stop and remove the service
end;
if CurUninstallStep = usPostUninstall then //Step happens after processing uninstall log

View File

@@ -18,6 +18,7 @@ var
products: array of TProduct;
delayedReboot, isForcedX86: boolean;
DependencyPage: TOutputProgressWizardPage;
AdditionalMemo: string;
procedure AddProduct(filename, parameters, title, size, url: string; forceSuccess, installClean, mustRebootAfter : boolean);
{
@@ -228,6 +229,8 @@ begin
if MemoTasksInfo <> '' then
s := s + MemoTasksInfo;
s := s + AdditionalMemo;
Result := s
end;