In generale creare installazioni per i propri programmi (.NET o meno) è abbastanza facile, visto che sia il Visual Studio 2003/2005 che il Visual Studio Installer semplificano di molto le cose.

Sinceramente però non avevo mai creato applicazioni mobile che necessitassero di un setup "professionale", e memore delle mie precedenti esperienze disastrose  con cab e deploy vari (in ActiveX su IE) temevo di "non cavarci le gambe"...

E invece è andata molto bene, in mezza giornatina ho fatto tutto, pure con molta tranquillità, e ora vi racconto come ho fatto... sempre che ve ne freghi qualcosa

Allora, la bibbia è tutta qui, in Developing and Deploying Pocket PC Setup Application (pure su msdn), in  cui è spiegato in modo dettagliato la procedura e c'è uno "scheletro di codice" da cui partire e da modificare alla bisogna.

Vi invito a fare riferimento all'articolo per ogni spiegazione, visto che è davvero molto comprensibile e ben fatto, e segnalo solo quel paio di cose che ho riscontrato nella mia esperienza (chiaramente se non leggete prima l'articolo tutto vi sembrerà astruso e incomprensibile...).

Sostanzialmente occorre creare un file setup.ini, che descrive in poche righe il programma, e modificare i file buildcab.bat e nomeprogramma.inf creati dentro la cartella obj del vostro progetto PPC.

Il file setup.inf è banale, tanto che si può prendere benissimo quello del codice di esempio e modificare il poco che serve:

[CEAppManager]
Version      = 1.0
Component    = App

[App]
Description  = Descrizione del programma.
CabFiles     = NomeProgr_PPC.X86.CAB,NomeProgr_PPC.ARM.CAB,NomeProgr_PPC.ARMV4.CAB,NomeProgr_PPC.MIPS.CAB,NomeProgrPPC.SH3.CAB,NomeProgr_PPC.WCE420X86.CAB

Per quanto riguarda BuildCab.bat, il comando che vi permette di generare i cab per le diversi dispositivi Pocket PC o Win CE (ARM, X86, MIPS, ecc...), l'unica cosa da segnalare è la comodita intrinseca che offre la definizione degli eventi di pre-build. In pratica ad ogni compilazione del vostro eseguibile, VS 2003 esegue in automatico la creazione dei cab, aggiornando automaticamente i files!  (Vado di fretta perchè l'articolo spiega molto bene questa parte...)

Il cuore della vostra installazione è però il file nomeprogramma.inf, che in pratica guida tutto il processo di copia dei files del vostro programma sul dispositivo.

Questa parte va spiegata. Occorre infatti specificare che un installer per dispositivi Windows Mobile "vive" di due fasi distinte, che sono (ovviamente) l'installazione sul PC desktop dell'utente dei cab del programma mobile e l'installazione sul dispositivo connesso al PC tramite ActiveSync del programma vero e proprio; mentre la prima parte viene configurata tramite i tradizionali strumenti del Visual Studio (i progetti di deploy), quest'ultima parte viene descritta TOTALMENTE dal file INF. Se quindi vi occorre copiare delle chiavi di registro o files addizionali in determinate cartelle del dispositivo, dovete scrivervi a mano l'inf adatto a voi e non potete fare affidamento in alcun modo sui wizard del Visual Studio, che, ripeto, si riferiscono alla machhina desktop e non al palmare.

Fortunatamante anche questa parte è ben documentata: sempre partendo dal file inf di base generato per voi dal Visual Studio, occorre aggiungere quello che vi serve basandosi sulle linee guida che trovate qui.

Riporto uno stralcio del file inf che mi sono creato a partire da quello di base (occhi ai commenti!):

[Version]
Signature="$Windows NT$"
Provider="MiaDitta"
CESignature="$Windows CE$"

[CEStrings]
AppName="MiaApplicazione"
InstallDir=%CE1%\%AppName%   // %CE1% e vari sono le cartelle predefinite sul palmare

[CEDevice]
VersionMin=3.00
VersionMax=4.99

[DefaultInstall]
CEShortcuts=Shortcuts
CopyFiles=Files.Common,Files.WinConfig    

// Files.WinConfig l'ho creata come sezione addizionale
// Qui la richiamo dopo aver eseguito la sezione Files.WinConfig 
// generata in automatico da VS 2003

[DefaultInstall.ARMV4]
CopyFiles=Files.ARMV4
CESetupDLL=vsd_setup.dll

// ... seguono sezioni per i vari tipi di dispositivi...

[SourceDisksNames]
1=,"Common1",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\MiaApp\obj\Release\"
2=,"Common2",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\MiaApp\"
3=,"Common3",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\MiaApp\"
4=,"Common4",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\MiaApp\BuildCabs\"
5=,"Common5",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\SmartDeviceFramework14\OpenNETCF.Xml\obj\Release\"
6=,"Common6",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\SmartDeviceFramework14\OpenNETCF.Net\obj\Release\"
7=,"Common7",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\SmartDeviceFramework14\OpenNETCF.Drawing\obj\Release\"
8=,"Common8",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\SmartDeviceFramework14\OpenNETCF\obj\Release\"
9=,"Common9",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\SmartDeviceFramework14\OpenNETCF.Web.Services2\obj\Release\"
10=,"Common10",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\SmartDeviceFramework14\OpenNETCF.Windows.Forms\obj\Release\"

[SourceDisksNames.ARMV4]
11=,"ARMV411",,"C:\Documents and Settings\Davide\Documenti\Visual Studio Projects\MiaApp\obj\Release\"
12=,"ARMV4_Setup",,"c:\Programmi\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce300\ARMV4\"

// ... seguono sezioni per i vari tipi di dispositivi...

[SourceDisksFiles]
MiaApp.exe=1
app.ico=2
MiaApp.exe.config=2            
// Questo file e il successivo li ho aggiunti a mano
machine.config=2            // 2 rappresenta la cartella(in SourceDisksNames] in cui risiedono
OnSiteClient_PPC.inf=4
OpenNETCF.Xml.dll=5
OpenNETCF.Net.dll=6
OpenNETCF.Drawing.dll=7
OpenNETCF.dll=8
OpenNETCF.Web.Services2.dll=9
OpenNETCF.Windows.Forms.dll=10

[SourceDisksFiles.ARMV4]
vsd_config.txt.ARMV4=11
vsd_setup.dll=12

// ... seguono sezioni per i vari tipi di dispositivi...

[DestinationDirs]
Files.Common=0,%InstallDir%
Files.WinConfig=0,%CE2%\config    
// Aggiunta a mano, IMPORTANTE, vedi il post...
Shortcuts=0,%CE2%\Start Menu
Files.ARMV4=0,%InstallDir%
Files.ARM=0,%InstallDir%
Files.SH3=0,%InstallDir%
Files.MIPS=0,%InstallDir%
Files.X86=0,%InstallDir%
Files.WCE420X86=0,%InstallDir%

[Files.Common]
MiaApp,,,0
MiaApp.exe.config,,,0        
// Aggiunto a mano, è un file che andrà insieme all'exe
app.ico,,,0
OnSiteClient_PPC.inf,,,0
OpenNETCF.Xml.dll,,,0
OpenNETCF.Net.dll,,,0
OpenNETCF.Drawing.dll,,,0
OpenNETCF.dll,,,0
OpenNETCF.Web.Services2.dll,,,0
OpenNETCF.Windows.Forms.dll,,,0

[Files.WinConfig]        
// Sezione aggiunta a mano, andra in \Windows\config
machine.config,,,0        // Vedi DestinationDirs

[Files.ARMV4]
vsd_config.txt,vsd_config.txt.ARMV4,,0
vsd_setup.dll,,,0

// ... seguono sezioni per i vari tipi di dispositivi...

[Shortcuts]
MiaApp,0,MiaApp.exe,%CE11%

L'unico "scoglio" che ho riscontrato è l'impossibilità di definire copiare files in cartelle diverse dalla directory di installazione, definita nella sezione [CEStrings] come:

AppName="MiaApplicazione"
InstallDir=%CE1%\%AppName%

se non usando questa sintassi:

[DestinationDirs]
Files.Common=0,%InstallDir%
Files.WinConfig=0,%CE2%\config

Inizialmente avevo creato una sezione CEStrings in questo modo:

AppName="MiaApplicazione"
WinDir="config"
InstallDir=%CE1%\%AppName%
WinConfig=%CE2%\%WinDir%

e

Files.WinConfig=0,WinConfig

Entrambe le sintassi dovrebbero essere valide, ma nel secondo caso i files venivano copiati nella root del dispositivo in una cartella nominata %WinDir%, segno che c'era qualche confusione della creazione/gestione delle variabili d'ambiente...

Per quanto riguarda invece la procedura di gestione dell'installazione tramite ActiveSync, tutto è demandato ad una dll esterna, che va inclusa nel progetto di setup. La dll contiene una classe che eredita da System.Configuration.Install.Installer e implementa il codice di gestione negli eventi AfterInstall e AfterUninstall:

private void Installer_AfterInstall(object sender, System.Configuration.Install.InstallEventArgs e)
{
    
// Get fullpath to .ini file
    
string arg = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Setup.ini");
    
    
// Run WinCE App Manager to install .cab file on device
    
RunAppManager(arg);
}

private void Installer_AfterUninstall(object sender, System.Configuration.Install.InstallEventArgs e)
{
    
// Run app manager in uninstall mode (without any arguments)
    
RunAppManager(null);
}

private void RunAppManager(string arg)
{
    
// Get path to the app manager
    
const string RegPath = @"Software\Microsoft\Windows\" + 
        @"CurrentVersion\App Paths\CEAppMgr.exe";
    RegistryKey key = Registry.LocalMachine.OpenSubKey(RegPath);                    
    
string appManager = key.GetValue("") as string;
    
    
if (appManager != null)        // Launch the app            
        
Process.Start(string.Format("\"{0}\"", appManager), (arg == null) ? "" : string.Format("\"{0}\"", arg));
    
else    // Could not locate app manager
        
MessageBox.Show("Could not launch the WinCE Application Manager.");
}

powered by IMHO 1.3