JT2GO: - Inno Setup installer for JT2Go with prerequisite checking - Checks for VC++ x86/x64 redistributables and .NET 4.8 - Verifies admin privileges before installation - Supports silent installation mode NetworkDriveManager: - Full Inno Setup implementation with integrated PowerShell logic - Menu-based interface for managing legacy domain network drives - Features: backup/restore mappings, credential testing, drive reset - Server migration from rd.ds.ge.com to wjs.geaerospace.net - Three-phase reconnection to prevent error 1219 with multiple shares - Add predefined drives (S:, V:, Y:) functionality Template: - Reusable Inno Setup project template for co-workers - Documented sections with examples and best practices - Includes utility functions and common patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
464 lines
16 KiB
Plaintext
464 lines
16 KiB
Plaintext
; ============================================================================
|
|
; INNO SETUP PROJECT TEMPLATE
|
|
; ============================================================================
|
|
;
|
|
; This template provides a starting point for creating Inno Setup installers.
|
|
; It includes common patterns, examples, and best practices.
|
|
;
|
|
; HOW TO USE THIS TEMPLATE:
|
|
; 1. Copy this entire folder to a new location
|
|
; 2. Rename Template.iss to YourProjectName.iss
|
|
; 3. Search for "TODO:" comments and update as needed
|
|
; 4. Add your files to the project folder
|
|
; 5. Compile with Inno Setup Compiler
|
|
;
|
|
; REQUIREMENTS:
|
|
; - Inno Setup 6.x or later (https://jrsoftware.org/isinfo.php)
|
|
; - Optional: Add gea-logo.ico, banner.bmp, banner-sm.bmp for branding
|
|
;
|
|
; Author: WJDT / GE Aerospace
|
|
; Version: 1.0
|
|
; ============================================================================
|
|
|
|
; ============================================================================
|
|
; [Setup] - Basic installer configuration
|
|
; ============================================================================
|
|
[Setup]
|
|
; TODO: Generate a unique GUID for your app (Tools > Generate GUID in Inno Setup)
|
|
AppId={{YOUR-UNIQUE-GUID-HERE}}
|
|
|
|
; TODO: Update these with your application details
|
|
AppName=My Application Name
|
|
AppVersion=1.0
|
|
AppPublisher=WJDT
|
|
AppPublisherURL=https://www.geaerospace.com
|
|
AppSupportURL=https://www.geaerospace.com
|
|
AppUpdatesURL=https://www.geaerospace.com
|
|
|
|
; Installation directory (use {autopf} for Program Files, auto-selects 32/64-bit)
|
|
DefaultDirName={autopf}\My Application
|
|
|
|
; Start menu folder name
|
|
DefaultGroupName=My Application
|
|
|
|
; Output settings
|
|
OutputDir=Output
|
|
OutputBaseFilename=MyApplicationSetup_v1.0
|
|
|
|
; Compression
|
|
SolidCompression=yes
|
|
Compression=lzma2
|
|
|
|
; Visual style
|
|
WizardStyle=modern
|
|
|
|
; Branding (included in template - replace with your own)
|
|
SetupIconFile=gea-logo.ico
|
|
WizardImageFile=banner.bmp
|
|
WizardSmallImageFile=banner-sm.bmp
|
|
|
|
; Privileges: admin = requires elevation, lowest = current user only
|
|
; Use 'admin' for Program Files installs, 'lowest' for user-specific tools
|
|
PrivilegesRequired=admin
|
|
|
|
; Other common options
|
|
DisableWelcomePage=no
|
|
DisableDirPage=no
|
|
DisableProgramGroupPage=no
|
|
AllowNoIcons=yes
|
|
|
|
; Uninstall settings
|
|
Uninstallable=yes
|
|
CreateUninstallRegKey=yes
|
|
|
|
; ============================================================================
|
|
; [Languages] - Supported languages
|
|
; ============================================================================
|
|
[Languages]
|
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
|
; Uncomment for additional languages:
|
|
; Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
|
; Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
|
; Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
|
|
|
; ============================================================================
|
|
; [Messages] - Custom message overrides
|
|
; ============================================================================
|
|
[Messages]
|
|
; TODO: Customize the welcome page text
|
|
WelcomeLabel2=This will install [name] version [ver] on your computer.%n%nIt is recommended that you close all other applications before continuing.%n%nClick Next to continue, or Cancel to exit Setup.
|
|
|
|
; ============================================================================
|
|
; [Tasks] - Optional installation tasks (checkboxes)
|
|
; ============================================================================
|
|
[Tasks]
|
|
Name: "desktopicon"; Description: "Create a &desktop shortcut"; GroupDescription: "Additional shortcuts:"; Flags: unchecked
|
|
Name: "quicklaunchicon"; Description: "Create a &Quick Launch shortcut"; GroupDescription: "Additional shortcuts:"; Flags: unchecked
|
|
; Example: Optional component
|
|
; Name: "installextra"; Description: "Install optional components"; GroupDescription: "Components:"
|
|
|
|
; ============================================================================
|
|
; [Files] - Files to install
|
|
; ============================================================================
|
|
[Files]
|
|
; TODO: Add your application files here
|
|
;
|
|
; Common flags:
|
|
; ignoreversion - Always overwrite regardless of version
|
|
; recursesubdirs - Include subdirectories
|
|
; createallsubdirs - Create empty subdirectories too
|
|
; deleteafterinstall - Delete after install (for temp files)
|
|
;
|
|
; Examples:
|
|
; Source: "MyApp.exe"; DestDir: "{app}"; Flags: ignoreversion
|
|
; Source: "MyApp.dll"; DestDir: "{app}"; Flags: ignoreversion
|
|
; Source: "Data\*"; DestDir: "{app}\Data"; Flags: ignoreversion recursesubdirs createallsubdirs
|
|
; Source: "README.txt"; DestDir: "{app}"; Flags: ignoreversion isreadme
|
|
|
|
; ============================================================================
|
|
; [Dirs] - Directories to create
|
|
; ============================================================================
|
|
[Dirs]
|
|
; Example: Create a data directory with specific permissions
|
|
; Name: "{app}\Data"; Permissions: users-modify
|
|
; Name: "{commonappdata}\MyApp"; Permissions: users-modify
|
|
|
|
; ============================================================================
|
|
; [Icons] - Shortcuts to create
|
|
; ============================================================================
|
|
[Icons]
|
|
; Start Menu shortcut
|
|
; Name: "{group}\My Application"; Filename: "{app}\MyApp.exe"; WorkingDir: "{app}"
|
|
|
|
; Desktop shortcut (only if task selected)
|
|
; Name: "{userdesktop}\My Application"; Filename: "{app}\MyApp.exe"; WorkingDir: "{app}"; Tasks: desktopicon
|
|
|
|
; Uninstall shortcut in Start Menu
|
|
; Name: "{group}\Uninstall My Application"; Filename: "{uninstallexe}"
|
|
|
|
; ============================================================================
|
|
; [Registry] - Registry entries
|
|
; ============================================================================
|
|
[Registry]
|
|
; Examples:
|
|
; Root: HKLM; Subkey: "Software\MyCompany\MyApp"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"; Flags: uninsdeletekey
|
|
; Root: HKCU; Subkey: "Software\MyCompany\MyApp"; ValueType: dword; ValueName: "SomeOption"; ValueData: "1"
|
|
|
|
; ============================================================================
|
|
; [INI] - INI file entries
|
|
; ============================================================================
|
|
[INI]
|
|
; Example: Create an INI file
|
|
; Filename: "{app}\MyApp.ini"; Section: "Settings"; Key: "Language"; String: "en"
|
|
|
|
; ============================================================================
|
|
; [Run] - Programs to run after installation
|
|
; ============================================================================
|
|
[Run]
|
|
; Example: Launch app after install (optional, user can uncheck)
|
|
; Filename: "{app}\MyApp.exe"; Description: "Launch My Application"; Flags: nowait postinstall skipifsilent
|
|
|
|
; Example: Run a configuration script
|
|
; Filename: "{cmd}"; Parameters: "/c ""{app}\configure.bat"""; Flags: runhidden waituntilterminated
|
|
|
|
; ============================================================================
|
|
; [UninstallRun] - Programs to run during uninstall
|
|
; ============================================================================
|
|
[UninstallRun]
|
|
; Example: Run cleanup script before uninstall
|
|
; Filename: "{app}\cleanup.bat"; Flags: runhidden waituntilterminated
|
|
|
|
; ============================================================================
|
|
; [UninstallDelete] - Additional files to delete during uninstall
|
|
; ============================================================================
|
|
[UninstallDelete]
|
|
; Example: Delete log files created by the app
|
|
; Type: files; Name: "{app}\*.log"
|
|
; Type: filesandordirs; Name: "{app}\Cache"
|
|
|
|
; ============================================================================
|
|
; [Code] - Pascal scripting section
|
|
; ============================================================================
|
|
[Code]
|
|
|
|
// ============================================================================
|
|
// CONSTANTS
|
|
// ============================================================================
|
|
|
|
const
|
|
// TODO: Add your constants here
|
|
APP_NAME = 'My Application';
|
|
|
|
// ============================================================================
|
|
// GLOBAL VARIABLES
|
|
// ============================================================================
|
|
|
|
var
|
|
// Custom wizard pages (if needed)
|
|
CustomPage: TWizardPage;
|
|
|
|
// Progress page for long operations
|
|
ProgressPage: TOutputProgressWizardPage;
|
|
|
|
// ============================================================================
|
|
// UTILITY FUNCTIONS
|
|
// ============================================================================
|
|
|
|
// Execute a command and capture output
|
|
function ExecWithOutput(const Cmd, Params: String; var Output: String): Integer;
|
|
var
|
|
TempFile: String;
|
|
ResultCode: Integer;
|
|
OutputAnsi: AnsiString;
|
|
begin
|
|
TempFile := ExpandConstant('{tmp}\exec_output.txt');
|
|
|
|
Exec('cmd.exe', '/c ' + Cmd + ' ' + Params + ' > "' + TempFile + '" 2>&1',
|
|
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
|
|
|
if FileExists(TempFile) then
|
|
begin
|
|
LoadStringFromFile(TempFile, OutputAnsi);
|
|
Output := String(OutputAnsi);
|
|
DeleteFile(TempFile);
|
|
end
|
|
else
|
|
Output := '';
|
|
|
|
Result := ResultCode;
|
|
end;
|
|
|
|
// Execute a PowerShell script and capture output
|
|
function ExecPowerShell(const Script: String; var Output: String): Integer;
|
|
var
|
|
TempScript, TempOutput: String;
|
|
ResultCode: Integer;
|
|
OutputAnsi: AnsiString;
|
|
begin
|
|
TempScript := ExpandConstant('{tmp}\ps_script.ps1');
|
|
TempOutput := ExpandConstant('{tmp}\ps_output.txt');
|
|
|
|
SaveStringToFile(TempScript, Script, False);
|
|
|
|
Exec('cmd.exe',
|
|
'/c powershell.exe -NoProfile -ExecutionPolicy Bypass -File "' + TempScript + '" > "' + TempOutput + '" 2>&1',
|
|
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
|
|
|
if FileExists(TempOutput) then
|
|
begin
|
|
LoadStringFromFile(TempOutput, OutputAnsi);
|
|
Output := String(OutputAnsi);
|
|
DeleteFile(TempOutput);
|
|
end
|
|
else
|
|
Output := '';
|
|
|
|
DeleteFile(TempScript);
|
|
Result := ResultCode;
|
|
end;
|
|
|
|
// Check if a program is installed (by checking registry)
|
|
function IsProgramInstalled(const DisplayName: String): Boolean;
|
|
var
|
|
Subkey: String;
|
|
Value: String;
|
|
begin
|
|
Result := False;
|
|
// Check 64-bit registry
|
|
Subkey := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + DisplayName;
|
|
if RegQueryStringValue(HKLM, Subkey, 'DisplayName', Value) then
|
|
Result := True
|
|
else
|
|
begin
|
|
// Check 32-bit registry on 64-bit Windows
|
|
Subkey := 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' + DisplayName;
|
|
if RegQueryStringValue(HKLM, Subkey, 'DisplayName', Value) then
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
// Check if .NET Framework 4.8 is installed
|
|
function IsDotNet48Installed: Boolean;
|
|
var
|
|
Release: Cardinal;
|
|
begin
|
|
Result := False;
|
|
if RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', Release) then
|
|
Result := (Release >= 528040); // 4.8 or later
|
|
end;
|
|
|
|
// Check if VC++ Redistributable is installed (2015-2022)
|
|
function IsVCRedistInstalled: Boolean;
|
|
var
|
|
Installed: Cardinal;
|
|
begin
|
|
Result := False;
|
|
if RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Installed', Installed) then
|
|
Result := (Installed = 1);
|
|
end;
|
|
|
|
// Show a modal message dialog with scrollable text
|
|
procedure ShowResultsDialog(const Title, Content: String);
|
|
var
|
|
ResultForm: TSetupForm;
|
|
Memo: TNewMemo;
|
|
OKButton: TNewButton;
|
|
begin
|
|
ResultForm := CreateCustomForm;
|
|
ResultForm.Caption := Title;
|
|
ResultForm.ClientWidth := 500;
|
|
ResultForm.ClientHeight := 400;
|
|
ResultForm.Position := poScreenCenter;
|
|
|
|
Memo := TNewMemo.Create(ResultForm);
|
|
Memo.Parent := ResultForm;
|
|
Memo.Left := 10;
|
|
Memo.Top := 10;
|
|
Memo.Width := ResultForm.ClientWidth - 20;
|
|
Memo.Height := ResultForm.ClientHeight - 60;
|
|
Memo.ScrollBars := ssVertical;
|
|
Memo.ReadOnly := True;
|
|
Memo.Text := Content;
|
|
Memo.Font.Name := 'Consolas';
|
|
Memo.Font.Size := 9;
|
|
|
|
OKButton := TNewButton.Create(ResultForm);
|
|
OKButton.Parent := ResultForm;
|
|
OKButton.Caption := 'OK';
|
|
OKButton.Width := 80;
|
|
OKButton.Height := 30;
|
|
OKButton.Left := (ResultForm.ClientWidth - OKButton.Width) div 2;
|
|
OKButton.Top := ResultForm.ClientHeight - 45;
|
|
OKButton.ModalResult := mrOK;
|
|
OKButton.Default := True;
|
|
|
|
ResultForm.ShowModal;
|
|
ResultForm.Free;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// WIZARD PAGE CREATION
|
|
// ============================================================================
|
|
|
|
procedure InitializeWizard;
|
|
begin
|
|
// Create a progress page for long operations
|
|
ProgressPage := CreateOutputProgressPage('Please Wait',
|
|
'Please wait while the operation completes...');
|
|
|
|
// TODO: Create custom wizard pages here if needed
|
|
// Example: Create a custom input page
|
|
// CustomPage := CreateCustomPage(wpSelectDir, 'Custom Options', 'Configure additional options');
|
|
|
|
// Example: Add controls to custom page
|
|
// var MyLabel: TLabel;
|
|
// MyLabel := TLabel.Create(CustomPage);
|
|
// MyLabel.Parent := CustomPage.Surface;
|
|
// MyLabel.Caption := 'Enter your setting:';
|
|
// MyLabel.Left := 0;
|
|
// MyLabel.Top := 0;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// INSTALLATION EVENTS
|
|
// ============================================================================
|
|
|
|
// Called at the very start - return False to abort
|
|
function InitializeSetup: Boolean;
|
|
begin
|
|
Result := True;
|
|
|
|
// Example: Check for admin rights
|
|
if not IsAdmin then
|
|
begin
|
|
MsgBox('This installer requires administrator privileges.' + #13#10 +
|
|
'Please right-click and select "Run as administrator".',
|
|
mbError, MB_OK);
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
|
|
// Example: Check prerequisites
|
|
// if not IsDotNet48Installed then
|
|
// begin
|
|
// MsgBox('.NET Framework 4.8 is required but not installed.', mbError, MB_OK);
|
|
// Result := False;
|
|
// Exit;
|
|
// end;
|
|
end;
|
|
|
|
// Called before each wizard page - return True to skip the page
|
|
function ShouldSkipPage(PageID: Integer): Boolean;
|
|
begin
|
|
Result := False;
|
|
// Example: Skip directory page for portable install
|
|
// if PageID = wpSelectDir then
|
|
// Result := True;
|
|
end;
|
|
|
|
// Called when Next button is clicked - return False to stay on page
|
|
function NextButtonClick(CurPageID: Integer): Boolean;
|
|
begin
|
|
Result := True;
|
|
|
|
// Example: Validate custom page input
|
|
// if CurPageID = CustomPage.ID then
|
|
// begin
|
|
// if MyEdit.Text = '' then
|
|
// begin
|
|
// MsgBox('Please enter a value.', mbError, MB_OK);
|
|
// Result := False;
|
|
// end;
|
|
// end;
|
|
end;
|
|
|
|
// Called at each installation step
|
|
procedure CurStepChanged(CurStep: TSetupStep);
|
|
var
|
|
ResultCode: Integer;
|
|
begin
|
|
// ssInstall: Before files are installed
|
|
// ssPostInstall: After files are installed
|
|
// ssDone: Installation complete
|
|
|
|
if CurStep = ssPostInstall then
|
|
begin
|
|
// Example: Run post-install configuration
|
|
// Exec(ExpandConstant('{app}\configure.exe'), '/silent', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
|
end;
|
|
end;
|
|
|
|
// Called at each uninstallation step
|
|
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
|
begin
|
|
// usAppMutexCheck: Check for running app
|
|
// usUninstall: Before uninstall
|
|
// usPostUninstall: After uninstall
|
|
// usDone: Uninstall complete
|
|
|
|
if CurUninstallStep = usUninstall then
|
|
begin
|
|
// Example: Backup user data before uninstall
|
|
end;
|
|
end;
|
|
|
|
// ============================================================================
|
|
// SILENT INSTALL SUPPORT
|
|
// ============================================================================
|
|
|
|
// To run silently: MySetup.exe /VERYSILENT /SUPPRESSMSGBOXES
|
|
// To run silently with log: MySetup.exe /VERYSILENT /LOG="install.log"
|
|
|
|
// Check if running in silent mode
|
|
function IsSilentMode: Boolean;
|
|
begin
|
|
Result := WizardSilent;
|
|
end;
|
|
|
|
// Show message only if not in silent mode
|
|
procedure ShowMessageIfNotSilent(const Msg: String; MsgType: TMsgBoxType);
|
|
begin
|
|
if not WizardSilent then
|
|
MsgBox(Msg, MsgType, MB_OK);
|
|
end;
|