Technology Experience

Contenuti gestiti da Igor Damiani
posts - 949, comments - 2741, trackbacks - 15120

My Links

News

  • Questo blog si propone di raccogliere riflessioni, teoriche e pratiche, su tutto quello che riguarda il world-computing che mi sta attorno: programmazione in .NET, software attuale e futuro, notizie provenienti dal web, tecnologia in generale, open-source.

    L'idea è quella di lasciare una sorta di patrimonio personale, una raccolta di idee che un giorno potrebbe farmi sorridere, al pensiero di dov'ero e cosa stavo facendo.

    10/05/2005,
    Milano

Archives

Post Categories

Generale

[MCAD.40] Customizzare al 100% il nostro setup

Se le custom dialog preconfezionate non ci soddisfano, se le launch conditions dovrebbero essere un po' più complesse, se abbiamo la necessità di creare un qualcosa che non è possibile creare con le caratteristiche base di Windows Installer, possiamo coprire questo gap semplicemente sfruttando come si deve il nostro amico framework. Creando una nuova Class Library e creando una classe che eredita da  System.Configuration.Install.Installer possiamo piegare ai nostri scopi e fare tutto quello che vogliamo. La cosa magari non è semplicissima, ma per me è stato talmente tanto divertente ed appagante che voglio raccontare quello che ho fatto.

Creare una Class Library ed ereditare da  System.Configuration.Install.Installer
Dunque, abbiamo già parlato l'altra volta di come è organizzata la mia solution. In questo momento, il mio VS.NET ha aperto una solution con due progetti: l'applicazione, e il setup dell'applicazione stessa.
Per comodità, ho aggiunto un terzo progetto, di tipo Class Library e l'ho chiamato ManageSetup. Vs.NET crea come al solito un classe Class1 che ho immediatamente eliminato. Ho aggiunto invece un Item di tipo Installer Class e l'ho chiamato ManageSetup. Cosa abbiamo creato? Vediamolo.

Nel Solution Explorer ho aperto il file ManageSetup.cs.
La classe contenuta in questo file è definita come:

[RunInstaller(true)]
public class ManageSetup : System.Configuration.Install.Installer

Ovvero, eredita per l'appunto da System.Configuration.Install.Installer, ed inoltre è "decorata" dall'attributo [RunInstaller(true )]. Abbiamo il solito costruttore e il Dispose(). Notare che se facciamo doppio-click su ManageSetup.cs VS.NET apre un bel designer, dove possiamo posizionare tutto quello che eventualmente ci serve (SqlConnection, SqlDataAdapter e chi ne ha più ne metta).

A questo punto dobbiamo decidere in quale momento vogliamo intervenire durante il setup. Se vogliamo fare un qualcosa prima che l'installazione cominci, dobbiamo fare l'overload del metodo Install. Se vogliamo fare un qualcosa dopo che l'installazione è terminata, overloadiamo Commit. Poi possiamo fare l'overloading di Uninstall e di Rollback. Io ho fatto diverse prove, tutte andate a buon fine:

  1. Tramite un custom dialog ho richiesto all'utente l'inserimento di una directory da creare automaticamente al termine del setup
  2. Tramite un custom dialog con i CheckBoxes, ho richiesto all'utente la volontà di aprire un sito Web al termine del setup
  3. Prima che il setup cominci, mostro una Windows Form per chiedere un activation code
  4. Al termine del setup, mando un'e-mail (su richiesta) all'autore del programma (cioè a me! )

In cui casi, ho fatto l'overloading di Install, in altri di Commit. Ecco un piccolo esempio di codice C#:

public override void Commit(IDictionary savedState)
{
    
base.Commit (savedState);

    System.Diagnostics.Process.Start(@"C:\WINNT\notepad.exe");
}

Questo metodo Commit viene automaticamente chiamato dal motore di Windows Installer durante la Commit, ovvero al termine del setup. In realtà, non basta creare questa Class Library : dobbiamo in qualche modo notificare nel Setup Project il fatto che vogliamo utilizzare questo assembly durante il setup. Ecco come fare!!!

Modifichiamo il setup
Torniamo nel Setup Project, apriamo la finestra dedicata al File System. Posizioniamoci nell'Application Folder, clicchiamo con il pulsante destro, poi su Add ed infine su Project Output. Dalla finestra di dialogo, selezioniamo Primary Output e confermiamo con Ok: VS.NET inserisce automaticamente nel File System un oggetto chiamato Primary output from ManageSetup (Active).

A questo punto, andiamo su View --> Editor --> Custom Actions. Clicchiamo con il pulsante destro sul nodo principale (Custom Actions), selezioniamo Add Custom Action, andiamo dentro Application Folder e selezioniamo Primary output from ManageSetup (Active). Nei nodi Install, Commit, Rollback e Uninstall apparirà il "legame" con la Class Library che abbiamo creato. Se compiliamo il progetto e proviamo a lanciarne l'installazione, vedremo che nel momento in cui il motore di Windows Installer genererà la Commit, verrà aperto il Blocco Note (questo ovviamente a patto di aver fatto l'overloading di Commit usando il codice C# che indicato più sopra).

Se volessimo creare una directory durante il setup, non dovremmo fare altro che:

  1. aggiungere un custom dialog TextBoxes (A), per esempio. Personalizzarlo come vogliamo. Definire la TextBox che contiene il nome della directory come DIR_NAME
  2. andare nella custom action, selezionare l'evento Commit (nel nostro caso). Compilare la property CustomActionData indicando nome_parametro = [valore_parametro]. Nel nostro caso, /DIR_NAME = [DIR_NAME]. Se avessimo più parametri, bisogna separarli con uno spazio. La CustomActionData permette di passare i parametri all'interno del contesto di esecuzione del CLR: in questo modo nel codice C# possiamo "prelevare" le informazioni inputate dall'utente ed elaborarle come vogliamo
  3. gestire l'evento Commit nella classe, prelevare i valori immessi dall'utente ed elaborarli. Nel nostro caso, leggere il parametro DIR_NAME (di tipo string) e usare la classe Directory per controllare l'esistenza della directory ed eventualmente crearla. Il codice può essere ad esempio questo:
public override void Commit(IDictionary savedState)
{
    
base.Commit (savedState);

    
string dir_name = this.Context.Parameters["DIR_NAME"];

    MessageBox.Show("Sto per creare la directory : " + dir_name);

    
if (! Directory.Exists(dir_name))
        Directory.CreateDirectory(dir_name);
}

Nella Class Library ho aggiunto le reference a System.Windows.Forms, così ho potuto usare la classe MessageBox, ed eventualmente mostrare Windows Forms a piacimento.

La logica è questa. Se avessimo avuto altre custom dialog, non cambierebbe nulla. La CustomActionData conterrebbe più parametri, nel codice C# avremmo più righe this.Context.Parameters["nome_parametro"]: tutto il resto è normalissimo codice per fare assolutamente quello che vogliamo. Io, come ho detto, ho usato le librarie Indy Sockets (freeware) per far spedirmi un'e-mail, se l'utente ha attivato una CheckBox.

Personalizzare un setup non è nient'altro che...usare il framework
E' vero, già da tempo i tool per la creazione di setup professionali permettono un'avanzata personalizzazione del processo di deployment. Però il più delle volte si tratta di imparare linguaggi di scripting dedicati, magari piuttosto ostici, e comunque con le loro limitazioni. Ed ancora: non c'è la possibilità di fare debug.

Questa volta invece abbiamo tutta la potenza del framework anche dentro il nostro setup.
Sia che usiate VB.NET o C#, basta che scriviate le vostre linee di codice per fare letteralmente quello che volete...non credo di aver mai avuto così tanto potere e così tanta flessibilità sotto le mani durante un setup creato da me...
Francamente, non vedo cosa potrei avere di meglio...

powered by IMHO 1.2

Print | posted on martedì 27 settembre 2005 16:13 | Filed Under [ MCAD ]

Feedback

Gravatar

# re: [MCAD.40] Customizzare al 100% il nostro setup

"Francamente, non vedo cosa potrei avere di meglio..."

installshield X :)
27/09/2005 16:39 | alessio.marziali
Gravatar

# Re: [MCAD.40] Customizzare al 100% il nostro setup

Sto provando il passaggio di più parametri nella CustomActionData ma vengono accettati solo nel formato:

/param1=value1 /param2=value2 /param3=value3
27/09/2005 17:53 | Mauro Sagratella
Gravatar

# re: [MCAD.40] Customizzare al 100% il nostro setup

hai fatto bene a correggermi...
il modo giusto è /param1 = value1

occhio però che se value1 in realtà è un parametro inserito in una TextBox, va indicato tra [], includendo il nome del parametro...il value ovviamente non lo puoi sapere a priori

quindi, se in un dialog hai messo una TextBox chiamata USERNAME, al momento del passaggio devi fare qualcosa tipo:
/USER = [USERNAME]
27/09/2005 18:54 | Igor Damiani
Gravatar

# [70-536, #27] Le classi Installer, InstallContext ed altre classi

28/03/2006 19:46 | Technology Experience
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET