Technology Experience
.NET World

MSBuild e la compilazione massiva di app Windows Phone 7

Oggi riprendo in mano Windows Live Writer per parlarvi di un’esigenza nata nei giorni scorsi, e che ho risolto (almeno tecnicamente) questa notte, anche se ho dovuto fare le ore piccole.

In questo momento, sul marketplace per Windows Phone 7 ci sono 21 applicazioni I Love Qualcosa (dove “Qualcosa” sta per Milan, Juventus, Roma, Palermo, Inter, etc. etc – il numero è disparsi perchè ho creato anche I Love Foppa, dedicata alla Foppapedretti Bergamo, squadra femminile di pallavolo). Le app sono ovviamente già disponibili da parecchio tempo (qualche mese) e nei giorni scorsi mi son posto la domanda: cosa dovrei fare se volessi ricompilarle tutte in modo massivo? Dal punto di vista tecnologico:

  1. E’ ovviamente un progetto di tipo Windows Phone 7
  2. E’ organizzata come unica solution ed unico project
  3. Esiste un file AssemblyInfo*.cs specifico per ogni squadra (quindi AssemblyInfoMilan.cs, AssemblyInfoInter.cs, e così via)
  4. Esiste un file WMAppManifest*.xml specifico per ogni squadra (quindi WMAppManifestMilan.xml, WMAppManifestInter.xml, e così via)
  5. I files dei punti (3) e (4) sono inclusi nel progetto (per maggiore facilità nella loro gestione) in folders dedicati, ed impostati come Build Action a None (in modo tale che non finiscono nel file .xap, il compilato finale)

Quindi, vi chiederete voi, come si fa ad ottenere I Love Milan piuttosto che I Love Inter?

Fino ad oggi questi passaggi li ho fatti manualmente. Supponiamo di voler generare ILoveMilan.xap.

  1. Copiavo il file AssemblyInfoAssemblyInfoMilan.cs in PropertiesAssemblyInfo.cs
  2. Copiavo il file WMAppManifestWMAppManifestMilan.xml in PropertiesWMAppManifest.xml
  3. Modificavo il file MainPage.xaml.cs per modificare una variabile stringa contenente il nome della squadra
  4. Entravo nelle proprietà del progetto per specificare il nome del file di output (in questo caso ILoveMilan.xap)

Tutto qua: poi lanciavo la compilazione e mi trovavo il file da inviare sul marketplace. Da notare che i files indicati ai punti (1) e (2) contengono una serie di importanti informazioni per l’app: titolo, descrizione, quali icone usare nelle varie dimensioni, etc. etc. Di fatto, sostituendoli, vengono sostituite informazioni essenziali dell’app stessa.

Quello che ho fatto stanotte è quindi automatizzare i quattro passaggi, inizialmente tentando di fare tutto con MSBuild.exe, poi rinunciando (causa scarsa conoscenza dello strumento) per passare ad una più “tradizionale” console application. C’è da dire questo: penso che non ci sia una soluzione unica e che vada bene per tutti, perchè ovviamente il tutto dipende da come avete strutturato la vostra solution. Vi racconto come ho fatto io.

Qualche dettaglio sulla console application
Il discorso è molto semplice. Ho creato un metodo generateTeam:

   1:  static void generateTeam(string team)
   2:  {
   3:      string path1;
   4:      string path2;
   5:   
   6:      path1 = baseDir + @"AssemblyInfoAssemblyInfo" + team + ".cs";
   7:      path2 = baseDir + @"PropertiesAssemblyInfo.cs";
   8:      File.Copy(path1, path2, true);
   9:   
  10:      path1 = baseDir + @"WMAppManifestWMAppManifest" + team + ".xml";
  11:      path2 = baseDir + @"PropertiesWMAppManifest.xml";
  12:      File.Copy(path1, path2, true);
  13:   
  14:      string mainPage = getResource("ConsoleApplication1.MainPage.xaml.cs1") + team + getResource("ConsoleApplication1.MainPage.xaml.cs2");
  15:      path1 = baseDir + "MainPage.xaml.cs";
  16:      File.WriteAllText(path1, mainPage);
  17:   
  18:      string csproj = getResource("ConsoleApplication1.ILoveFootballTeam.csproj1") + team + getResource("ConsoleApplication1.ILoveFootballTeam.csproj2");
  19:      path1 = baseDir + "ILoveFootballTeam.csproj";
  20:      File.WriteAllText(path1, csproj);
  21:   
  22:      msbuildClean();
  23:      msbuildCompile();
  24:   
  25:      path1 = baseDir + @"binReleaseILove" + team + ".xap";
  26:      if (File.Exists(path1))
  27:      {
  28:          path2 = @"X:OutputILove" + team + ".xap";
  29:          File.Copy(path1, path2, true);
  30:      }
  31:  }

 

Scusate la qualità del codice, ma alle 2 di notte non sono granchè! Sorriso

Alle righe 6-8 aggiorno e sovrascrivo il file AssemblyInfo.cs.

Alle righe 10-12 aggiorno e sovrascrivo il file WMAppManifest.xml.

Alle righe 14-16 sovrascrivo il file MainPage.xaml.cs, sfruttando un meccanismo “balordo” (ma che funziona!) con files Embedded Resource.

Alle righe 18-20 aggiorno il file .csproj, anche qui usando come template dei files inclusi come Embedded Resource.

Alla fine chiamo due metodi, msbuildClean() e msbuildCompile().

   1:  static void msbuildClean()
   2:  {
   3:      ProcessStartInfo start = new ProcessStartInfo();
   4:      start.FileName = @"C:WindowsMicrosoft.NETFrameworkv4.0.30319msbuild.exe";
   5:      start.Arguments = @" /p:Configuration=Release /t:Clean ILoveFootballTeam.csproj";
   6:      start.UseShellExecute = false;
   7:      start.WorkingDirectory = baseDir;
   8:      start.WindowStyle = ProcessWindowStyle.Normal;
   9:   
  10:      Process process = new Process();
  11:      process.StartInfo = start;
  12:      process.Start();
  13:      process.WaitForExit();
  14:  }

 

   1:  static void msbuildCompile()
   2:  {
   3:      ProcessStartInfo start = new ProcessStartInfo();
   4:      start.FileName = @"C:WindowsMicrosoft.NETFrameworkv4.0.30319msbuild.exe";
   5:      start.Arguments = @" /p:Configuration=Release ILoveFootballTeam.csproj";
   6:      start.UseShellExecute = false;
   7:      start.WorkingDirectory = baseDir;
   8:      start.WindowStyle = ProcessWindowStyle.Normal;
   9:   
  10:      Process process = new Process();
  11:      process.StartInfo = start;
  12:      process.Start();
  13:      process.WaitForExit();
  14:  }

 

IMPORTANTE: attenzione a NON usare l’msbuidl.exe contenuto in C:WindowsMicrosoft.NETFramework64v4.0.30319, perchè NON compila. Io stesso ho perso un sacco di tempo nel cercare di capire il perchè. Evidentemente, e probabilmente, il .NET Framework a 64 bit non c’entra nulla con wp7.

Eseguo msbuild.exe in due step separati: il primo fa la Clean della nostra binRelease, il secondo per effettuare la compilazione vera e propria.

Se tutto è andato a buon fine, prendo il file .xap generato e lo copio dove voglio io (righe 25-29 del primo blocco di codice).

Questo è il meccanismo che sta alla base. A questo punto è possibile chiamare generateTeam(“Milan”), generateTeam(“Cesena”), generateTeam(“Inter”), generateTeam(“Fiorentina”) per ottenere in una directory tutti gli .xap generati.

E adesso che abbiamo gli xap, come faccio ad inviarli sul marketplace?

Qui arrivano le note dolenti. E’ vero che in un battito di ciglia abbiamo le nuove versioni delle nostre app, ma per inviarle al marketplace occorre fare tutto manualmente, e qui non ci sono storie. Bisogna avere le icone nelle varie dimensioni, gli screenshots della nostra app, i testi e le descrizioni, etc. etc. E se avete 70 applicazioni (come l’amico Matteo), siete proprio fregati! Sorriso

Domande? Sono tutt’orecchi.

Send to Kindle

Igor Damiani

La sua passione per l'informatica nasce nella prima metà degli anni '80, quando suo padre acquistò un Texas Instruments TI-99. Da allora ha continuato a seguire l'evoluzione sia hardware che software avvenuta nel corso degli anni. E' un utente, un videogiocatore ed uno sviluppatore software a tempo pieno. Igor ha lavorato e lavora anche oggi con le più moderne tecnologie Microsoft per lo sviluppo di applicazioni: .NET Framework, XAML, Universal Windows Platform, su diverse piattaforme, tra cui spiccano Windows 10 piattaforme mobile. Numerose sono le app che Igor ha creato e pubblicato sul marketplace sotto il nome VivendoByte, suo personale marchio di fabbrica. Adora mantenere i contatti attraverso Twitter e soprattutto attraverso gli eventi delle community .NET.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.