Press "Enter" to skip to content

3 – Multiclock – Generare l’installer con InnoSetup

Se vogliamo distribuire agli utenti il nostro orologio multi fuso orario, è necessario creare un programma di setup semplice da usare da parte degli utenti stessi. Dopo che in visual studio, esattamente nella versione VS 2010 è stato tolto il progetto standard di setup Microsoft che produceva un .msi, sono passata a usare InnoSetup, un generatore di installer gratuito ma costruito con professionalità ed utilizzato da molti per distribuire le applicazioni desktop per Windows.

InnoSetup crea un file .exe che effettua l’installazione. Per farlo, ha bisogno di uno script che gli dica come la nostra applicazione è fatta, quali sono i file che la compongono, dove vogliamo installarla e come vogliamo sia configurata.

Gli script InnoSetup hanno 2 peculiarità che li rendono facili da utilizzare, tali peculiarità sono:

  1. E’ possibile includere diversi script uno nell’altro, pertanto si può modularizzare l’installazione.
  2. E’ possibile definire delle variabili, in modo da semplificare per quanto possibile la configurazione di una nuova applicazione.

Grazie a queste caratteristiche, preparare il setup di un’applicazione, dopo averlo fatto la prima volta, diventa molto, molto semplice.

Per il setup delle mie applicazioni, ho bisogno di 8 files:

  1. License.rtf, un file generato con word oppure wordpad che contiene i dati della licenza del software, per fare in modo che l’utente possa approvarla all’installazione.
  2. btn884.ico, l’icona dell’applicazione.
  3. MultiClock_li_small.bmp, è un file immagine con un nome per me convenzionale, potrebbe chiamarsi pippo.bmp volendo, vedremo dove viene inserito e dove viene usato. L’immagine è un BMP standard 55×55 pixel
  4. Multiclock_li.bmp, è anche questo un file immagine con un nome per me convenzionale, anche questo vedremo dove va inserito e come viene usato. L’immagine è un BMP standard 164 x 314 pixel
  5. ISS_DetectFramework4.iss, questo è uno script standard, non viene modificato mai perché è generico rispetto alle applicazioni, esegue uno script innosetup per controllare che il framework richiesto dall’applicazione sia installato sulla macchina. Nel mio caso, controlla che sia installato il framework 4.5.2 questo file sarà incluso nel file principale di installazione dell’applicazione.
  6. ISS_Version.iss, questo è uno script standard che contiene la versione del setup dell’applicazione, l’ho separato perché se necessario, costruire un batch o un utility per cambiare automaticamente la versione del prodotto sarebbe così molto semplice.
  7. ISS_Files.iss, questo è lo script che contiene la lista di tutti i files che compongono l’installazione, va aggiornato manualmente, oppure, io ho fatto una piccola utility console che va a rigenerarlo leggendo il file di progetto per verificare tutti i file che devono essere inseriti nel setup.  Tale utility è stata oggetto dell’articolo che precede questo e la sua discussione è disponibile a questo indirizzo. E’ indispensabile che teniate presente, che per creare correttamente il setup, InnoSetup necessita che tutte le librerie non parte del framework .Net siano presenti in locale sulla cartella su cui il file eseguibile del progetto viene creato, pertanto, controllate che sui Reference della vostra applicazione, tutte le DLL referenziate abbiano la property CopyLocal inizializzata a True. Inoltre, perché la vostra applicazione funzioni, se avete dei riferimenti multi livello, verificate di aver aggiunto il riferimento a tutte le DLL usate dal vostro eseguibile.
    Se vi chiedete cos’è un riferimento multilivello, tale riferimento è il seguente: Io ho una libreria che si chiama DnwBase.dll, ed ho una libreria che si chiama DnwUI.dll, DnwUI.dll ha al suo interno un reference a DnwBase.dll, nel mio progetto, utilizzo DnwUI.dll, non utilizzo direttamente DnwBase.dll, perché la mia applicazione funzioni correttamente, è indispensabile che io aggiunga nel progetto che genera l’eseguibile anche un riferimento esplicito a DnwBase.dll, altrimenti la mia applicazione si installerà, ma non funzionerà e molto probabilmente gli errori che solleverà saranno incomprensibili al povero utente. Pertanto tenetelo ben presente quando create delle librerie di uso comune per le vostre applicazioni e le riutilizzate in molte applicazioni diverse.
  8. ISS_Setup.iss, questo è lo script primario per generare il setup, in esso saranno definiti tutti i parametri di configurazione della vostra applicazione e saranno inclusi tutti gli altri file di script.

Una volta configurata la mia prima applicazione, per creare il setup di una nuova applicazione dovrò copiare questi files, modificare la versione e i parametri di configurazione su ISS_Setup, se necessario dovrò creare due immagini specifiche per l’applicazione, e dovrò modificare la lista dei files in ISS_Files, e nulla più.

Il contenuto dei files ISS

ISS.DetectFramework4.iss

//----------------------------------------------------------------------
// Attenzione questo va incluso dopo la clausola [code] di Innosetup
//----------------------------------------------------------------------
function IsDotNetDetected(version: string; service: cardinal): boolean;
// Indicates whether the specified version and service pack of the .NET Framework is installed.
//
// version -- Specify one of these strings for the required .NET Framework version:
//    'v1.1.4322'     .NET Framework 1.1
//    'v2.0.50727'    .NET Framework 2.0
//    'v3.0'          .NET Framework 3.0
//    'v3.5'          .NET Framework 3.5
//    'v4\Client'     .NET Framework 4.0 Client Profile
//    'v4\Full'       .NET Framework 4.0 Full Installation
//    'v4.5'          .NET Framework 4.5
//
// service -- Specify any non-negative integer for the required service pack level:
//    0               No service packs required
//    1, 2, etc.      Service pack 1, 2, etc. required
var
    key: string;
    install, release, serviceCount: cardinal;
    check45, success: boolean;
begin
    // .NET 4.5 installs as update to .NET 4.0 Full
    if version = 'v4.5' then begin
        version := 'v4\Full';
        check45 := true;
    end else
        check45 := false;
 
    // installation key group for all .NET versions
    key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + version;
 
    // .NET 3.0 uses value InstallSuccess in subkey Setup
    if Pos('v3.0', version) = 1 then begin
        success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
    end else begin
        success := RegQueryDWordValue(HKLM, key, 'Install', install);
    end;
 
    // .NET 4.0/4.5 uses value Servicing instead of SP
    if Pos('v4', version) = 1 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
    end else begin
        success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
    end;
 
    // .NET 4.5 uses additional value Release
    if check45 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
        success := success and (release >= 378389);
    end;
 
    result := success and (install = 1) and (serviceCount >= service);
end;
 
 
function InitializeSetup(): Boolean;
begin
    if not IsDotNetDetected('v4\Full', 0) then begin
        MsgBox('MyApp requires Microsoft .NET Framework 4.0 Full.'#13#13
            'Please use Windows Update or a local installer to install this version,'#13
            'and then re-run the RepsysConverter setup program.', mbInformation, MB_OK);
        result := false;
    end else
        result := true;
end;

Questo script, che trovate sul sito di Innosetup controlla l’esistenza del framework.net nella versione a noi più consona, come vedete,  nei commenti c’è indicato come configurarlo per qualsiasi framework. informerà i vostri utenti se il framework .Net che vi serve non fosse installato in modo che possano installarlo.

ISS_Version.iss

#define SrcApp "bin\release\MultiClock.exe"
#define MyAppVersion "2016.2"
#define MyVersionInfoVersion "2016.1.2.0"

Questo file è molto semplice, l’ho generato in questo modo, perché se volessimo incrementare automaticamente la versione ad ogni compilazione, sarebbe molto semplice creare un utility da linea di comando che lo riscriva o un file batch che lo aggiorni.

ISS_Files.iss

Source: "bin\Release\MultiClock.exe"; DestDir: {app}; Flags: IgnoreVersion;
Source: "bin\Release\MultiClock.vshost.exe.manifest"; DestDir: {app}; Flags: IgnoreVersion;
Source: "bin\Release\Newtonsoft.Json.dll"; DestDir: {app}; Flags: IgnoreVersion;
Source: "bin\Release\Newtonsoft.Json.xml"; DestDir: {app}; Flags: IgnoreVersion;

Per la nostra applicazione Multiclock, questo file è molto semplice, ma in una applicazione enterprise che fa uso di componenti di terze parti, di librerie proprietarie riutilizzabili e di altri file di supporto, questo file potrebbe contenere una lista molto lunga e non facile da manutenere manualmente, ecco perché abbiamo creato un utility che si occupa di includere tutto il necessario.

ISS_Setup.iss

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
 
#define MyAppName "MultiClock"
#define MyAppPublisher "Developed by Dotnetwork.it
#define MyAppURL "http://www.dotnetwork.it"
 
#include "ISS_Version.iss";
 
#define MyAppExeName "MultiClock.exe"
#define MyDestFolder "DNW"
#define MyLicenseFile "License.rtf"
#define MyIconFile "btn884.ico"
#define MyLogoInstall "MultiClock_li.bmp"
#define MyLogoInstallSmall "MultiClock_li_small.bmp"
#define MyAppGuid = "{{5BFF991A-7E06-4265-99AF-8D9F5BA4F129}
 
#define MyAppSettingsFolder = "\DNW\Settings\MultiClock\"
 
 
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={#MyAppGuid}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
VersionInfoVersion={#MyVersionInfoVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
;LDM start
;DefaultDirName={pf32}\{#MyDestFolder}\{#MyAppName}
DefaultDirName={pf}\{#MyDestFolder}\{#MyAppName}
;LDM end
DefaultGroupName={#MyDestFolder}
DisableProgramGroupPage=yes
LicenseFile={#MyLicenseFile}
OutputDir=..\InnoSetupCompiled
OutputBaseFilename={#MyAppName}Setup
SetupIconFile={#MyIconFile}
Compression=lzma
SolidCompression=yes
UninstallDisplayIcon={app}\{#MyAppExeName}
WizardImageBackColor=$542344
WizardImageFile={#MyLogoInstall}
WizardSmallImageFile={#MyLogoInstallSmall}
; "ArchitecturesInstallIn64BitMode=x64" requests that the install be
; done in "64-bit mode" on x64, meaning it should use the native
; 64-bit Program Files directory and the 64-bit view of the registry.
; On all other architectures it will install in "32-bit mode".
ArchitecturesInstallIn64BitMode=x64
 
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
 
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
;Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
 
[Files]
#include "ISS_Files.iss"
 
[Dirs]
Name: "{commonappdata}{#MyAppSettingsFolder}"; Permissions: authusers-readexec powerusers-full admins-full
 
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
;Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon
 
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
 
 
[code]
#include "ISS_DetectFramework4.iss"

Questo file è la parte più importante del nostro setup, ma grazie all’uso delle inclusioni, e all’uso delle variabili, la sola parte che va modificata creando il setup per una nuova applicazione è la seguente:

#define MyAppName "MultiClock"
#define MyAppPublisher "Developed by Dotnetwork.it"
#define MyAppURL "http://www.dotnetwork.it"
 
#include "ISS_Version.iss";
 
#define MyAppExeName "MultiClock.exe"
#define MyDestFolder "DNW"
#define MyLicenseFile "License.rtf"
#define MyIconFile "btn884.ico"
#define MyLogoInstall "MultiClock_li.bmp"
#define MyLogoInstallSmall "MultiClock_li_small.bmp"
#define MyAppGuid = "{{5BFF991A-7E06-4265-99AF-8D9F5BA4F129}"
 
#define MyAppSettingsFolder = "\DNW\Settings\MultiClock\"

Ho evidenziato le cose da modificare, la più importante è il campo MyAppGuid, questo codice, è un identificativo univoco dell’applicazione che viene utilizzato dal setup per aggiornare un app installata, pertanto deve essere univoco per ciascuna delle vostre applicazioni. Lo potete generare in Visual Studio

innosetup_guid_01

innosetup_guid_02

la doppia parentesi graffa all’inizio del valore della variabile serve perché le Graffe sono usate anche per altri scopi negli script di InnoSetup quindi è indispensabile metterla, mentre la finale basta singola.

Gli altri dati che possono e devono essere configurati sono:

  • MyAppName, il nome dell’applicazione (non dell’exe) ma per semplicità cerco di fare in modo sia una parola singola visto che sarà usato per generare il nome del file di setup.
  • MyAppPublisher, il nome di chi ha creato o vende l’applicazione
  • MyAppUrl, il sito su cui chiedere assistenza da parte degli utenti, se non ne usate uno dedicato, ovviamente mettete il sito aziendale.
  • MyAppExeName, è il nome dell’eseguibile dell’applicazione che ci serve per fare eseguire l’applicazione al termine del setup.
  • MyDestFolder, è la cartella base sotto Programmi dove verrà installato il programma, verrà composta aggiungendo una sottocartella con il nome applicazione, pertanto io di solito ne creo una specifica per l’azienda, nel nostro caso DNW sta per Dotnetwork.
  • MyLicenseFile, contiene il nome del file della licenza, in questo caso non ha path perché si trova sulla cartella dove si trova il file ISS
  • MyIconFile, contiene il nome dell’icona dell’applicazione, che sarà inserita anche nel file di setup prodotto. Anche in questo caso, non ha un path perché si trova sulla stessa cartella del file .ISS
  • MyLogoInstall, è il file più grande dei due BMP anche in questo caso, il solo nome file è usato perché si trova sulla stessa cartella dell’ISS, verrà usato nella finestra di setup.
  • MyLogoInstallSmall, è il file più piccolo dei due BMP, come il precedente se è sulla cartella dell’ISS non serve un path e come il file grande sarà usato nella finestra di setup.
  • MyAppSettingsFolder, in questo caso non serve, potremo eliminarla, è usata per indicare la cartella ove porre i parametri di configurazione applicativi, ma nel caso del clock non ve ne sono perché i dati di configurazione della nostra applicazione sono salvati sulla cartella documenti dell’utente.

Se osserviamo il resto dello script, possiamo verificare come, le variabili appena definite siano utilizzate per parametrizzare l’installazione in base all’applicazione.

Da qui in avanti, potete generare il setup di qualsiasi applicazione, aggiungendo le seguenti chiamate sul post build event del vostro progetto eseguibile:

IF /I '$(ConfigurationName)' EQU 'release' (
CALL "C:\Dotnetwork\InnoSetupFilesGen.exe" /v:minimum /p:$(ProjectPath) /d:$(OutDir) /o:ISS_Files.iss
CALL "%PROGRAMFILES%\Inno Setup 5\iscc.exe" "$(ProjectDir)ISS_Setup.iss"
)

Se compilate in configurazione ‘release’ da visual studio, eseguiamo prima l’utility di generazione e aggiornamento della lista dei files di progetto. Se non siete familiari con le variabili di ambiente di Visual Studio, e trovate strani i codici con i segni di $ nella chiamata alla nostra applicazione console, potete utilizzare il piccolo helper di visual studio che le mostra e permette di inserirle senza doverle scrivere a mano:

innosetup_postbuild

Dopo la nostra utility che rigenera il file ISS_Files.iss, viene chiamato il “compilatore” di InnoSetup passandogli il nome della cartella di progetto e il nome del file di script principale.

Sulla cartella automaticamente generata e predisposta verrà generato il file di setup:

innosetup_setup_01

Lanciando il file di setup, l’applicazione verrà installata sul sistema.

setup_01

La prima cosa che partirà sarà la schermata dello User Account Control, come potete notare, il Publisher è Unknown, questo perché non abbiamo un certificato digitale con cui abbiamo firmato il file di setup, se lo avessimo, verrebbe mostrato il nome di chi ha creato l’applicazione.

setup_02

Prima schermata, la lingua di installazione (se vi portate dietro i files di traduzione potete modificarla).

setup_03

La schermata di benvenuto e le informazioni sull’applicazione.

setup_04

La visualizzazione e accettazione della licenza.

setup_05

La cartella di destinazione

setup_06

La possibilità di avere l’icona sul desktop.

setup_07

Il riepilogo prima della conferma.

setup_08

Alla fine dell’installazione, potete lanciare l’applicazione.

Presumo abbiate notato, dove sono state usate le nostre immagini BMP di installazione e l’icona dell’applicazione.

Un ultimo consiglio prima del riepilogo: Io ho creato dei file per il setup con un nome generico, e una cartella di destinazione generica, in questo modo, per creare il setup di una nuova applicazione, mi basta copiare i file ISS, le icone (o crearne delle nuove specifiche se voglio) e il file License.rtf nel nuovo progetto, e modificare i dati delle variabili Soprattutto il GUID. Ma in 5 minuti un nuovo setup è funzionante.

Riepilogo

In questo articolo abbiamo visto le seguenti cose:

  • Come generare l’installer per una applicazione usando InnoSetup
  • Come sono fatti i files di script per la generazione dell’installer
  • Come usare il post build event di Visual Studio per generare l’installer quando compiliamo in release.
  • Come usare l’utility da noi descritta nel post precedente per automatizzare la generazione della lista dei file dell’applicazione.

Potete scaricare il progetto esempio dal link qui indicato:

Se volete invece installare l’orologio, questo è il link del setup

Per installare l’orologio scaricare lo zip, unzipparlo, contiene un file di setup al suo interno ed eseguirlo sul vostro computer.

Per qualsiasi domanda, osservazione, commento, approfondimento, o per segnalare un errore, potete usare il link alla form di contatto in cima alla pagina.