Nel post precedente ci eravamo interrotti sul più bello, ovvero sul contenuto del file batch DevOps.bat. Questo file ha un compito tanto importante quanto banale.
Ad ogni esecuzione deve produrre le cartelle per distribuire l’applicazione WPF secondo i tre modelli: WPF, Portable Zip e per il Windows Store.
Come nel post precedente, andiamo un passo alla volta ed arriveremo al risultato finale.
Primo passo: avere un folder per ciascun deploy
Le prime righe del file DevOps.bat fanno quanto segue:
@echo TASK - Remove and rebuild directories
rmdir "ClickOnce" /S /Q
rmdir "Portable" /S /Q
rmdir "Windows Store" /S /Q
mkdir "ClickOnce"
mkdir "Portable"
mkdir "Windows Store"
Abbiamo sostanzialmente a che fare con tre folder:
- ClickOnce
- Portable
- Windows Store
Direi che il nome è abbastanza esplicativo: ognuna di queste conterrà i file per ciascun deploy. I parametri del comando rmdir (ovvero /S e /Q) dicono di piallare ad ogni esecuzione tutto il contenuto delle cartelle e sottocartelle (/S), senza chiedere alcuna conferma (/Q).
Secondo passo: ClickOnce
Per generare automaticamente la cartella ClickOnce è necessario ricorrere a msbuild.
@echo TASK - ClickOnce
"C:Program Files (x86)MSBuild14.0inmsbuild.exe"
"..CharMapMe.sln" /target:publish /p:Configuration=Release
xcopy "..CharMapMeinReleaseapp.publish*.*"
"ClickOnce*.*" /E /Q /Y
Il primo comando esegue msbuild.exe dicendo di compilare il file CharMapMe.sln, nella configurazione Release, generando nel contempo la pubblicazione per ClickOnce.
Il risultato di questo comando è un folder “binReleaseapp.publish” che contiene solo ed esclusivamente i file specifici di ClickOnce. Ma non mi piace che sia dentro “app.publish”. Motivo per cui il secondo comando utilizza xcopy per copiare i file all’interno del folder “ClickOnce”.
E difatti, eccoli qua. E’ sufficiente prendere questa cartella ed inviarla via FTP per distribuire a tutti gli effetti l’ultima versione dell’applicazione.
Missione compiuta.
Terzo passo: Portable zip
Possiamo passare alla generazione del file zip per il download Portable.
I comandi contenuti nel file DevOps.bat sono i seguenti:
@echo TASK - Portable
xcopy "....CharMapMeinRelease*.*" "..Portable"
cd "..Portable"
del "*.pdb"
del "*.application"
del "*.config"
del "*vshost*"
del "*.manifest"
"..7z" a -tzip "CharMapMe.zip" -sdel -r *.*
In breve: copio tutti i file dalla “binRelease” nella mia cartella “Portable”. Inizialmente, questa cartella conterrà anche un certo numero di file che NON è necessario distribuire: ecco perchè le righe successive vanno a cancellare i file pdb, application, config, vshost e manifest.
Poi utilizzo 7z.exe (ricordate il post precedente? si trovava nella cartella Deploy) per creare al volo uno zip con tutti i file. Il parametro “-sdel” dice di rimuovere i file dopo la creazione del file zip. Il parametro “-r” dice di includere anche i file in eventuali sottocartelle, ma non è il nostro caso.
Fatto questo, nella cartella “Portable” ottengo il file “CharMapMe.zip”, pronto da mettere online.
Quarto passo: Windows Store
Il terzo modello di deploy prevede la distribuzione sul Windows Store.
La prima parte di comandi necessari sono i seguenti:
@echo TASK - Windows Store
xcopy "..CharMapMeinRelease*.*" "Windows Store"
xcopy "Support*.*" "Windows Store*.*" /Q /Y
cd "Windows Store"
del "*.pdb"
del "*.application"
del "*.config"
del "*vshost*"
del "*.manifest"
Sono praticamente gli stessi visti prima per la modalità Portable. Copio tutti i file dalla “binRelease” a “Windows Store”. Poi copio tutti quelli contenuti nella cartella “Support” nella cartella “Windows Store”: adesso vi dico la ragione di questa operazione. Poi, esattamente come prima, cancello quelli superflui, che non devono essere inclusi nel package.
A cosa serve la cartella “Support”? Essa contiene 4 file.
- AppxManifest.xml : è il file di manifest per l’applicazione UWP
- *.png : sono 3 tile in diverse dimensioni per creare il package UWP
E’ un po’ OT, in questo post, raccontare esattamente nel dettaglio questo passaggio. Facciamola breve: per distribuire un’app UWP ci vuole necessariamente un file di manifest. Sempre, in ogni caso. Ma CharMapMe NON è nata come app UWP, quindi il file di manifest l’ho dovuto creare da zero, con il blocco note. Idem le immagini per avere le tile. Per maggiori informazioni su questo particolare aspetto vi consiglio di leggere questo post sul blog di MSDN Italia.
Ok, fino a questo punto ci siamo. Nella cartella “Windows Store” ci sono i file necessari per creare il package: tutti quelli contenuti in “binRelease” + file di manifest + 3 immagini per le tile. Possiamo generare il file di package vero e proprio.
"C:Program Files (x86)Windows Kits10inx64makeappx.exe"
pack -d . -p "CharMapMe_nosigned.appx"
Eseguo il tool makeappx.exe, dicendo di prendere la cartella corrente, e di generare il file “CharMapMe_nosigned.appx”.
Poi mi duplico il file con il nome “CharMapMe_signed.appx”
copy "CharMapMe_nosigned.appx" "CharMapMe_signed.appx" /Y
Perchè avere due file? Quello “nosigned” sarà quello che invieremo sul Dev Center per tentare la certificazione, mentre quello “signed” potrà essere installato sulla nostra macchina (o su altre di sviluppo e/o test) per testare l’installer vero e proprio, e capire se l’app WPF convertita in UWP parte e funziona correttamente come previsto. Come faccio a firmare un file .appx?
SignTool sign /fd SHA256 /a /f
..VivendoByte.pfx /p 123456
CharMapMe_signed.appx
Utilizzo il tool SignTool per firmare il file “CharMapMe_signed.appx”, passando come parametri il certificato digitale “VivendoByte.pfx”, la password e l’algoritmo di cifratura (SHA256). Fatto, il package è firmato. Ripeto, ne abbiamo due: quello “nosigned” va inviato sul Dev Center, oppure all’ingegnere Microsoft con cui state collaborando per certificare la vostra app; quello “signed” serve a voi e solo a voi per testare la vostra app.
Infine, giusto per fare un lavoro pulito, cancello tutti i file nel folder “Windows Store” che non hanno l’estensione .appx. Così facendo, ottengo una bella cartella pulita con solo i due file package.
for /f %%F in ('dir /b /a-d ^| findstr /vile ".appx"') do del "%%F"
Per ottenere quindi una cosa simile:
Conclusioni
Beh, missione compiuta! Ci sarebbe molto altro da dire o da raccontare, per esempio:
- Posso mettere DevOps.bat nelle “post build events” di Visual Studio?
- Perchè non effettuare davvero il deploy in produzione, facendo l’upload dei file nel posto giusto? Ad eccezione del deploy del Windows Store, perchè quest’ultimo ad oggi passa ancora attraverso una procedura manuale di submission
- Eseguire “DevOps.bat > DevOps.log” permette di ottenere il log dell’ultima esecuzione, il che può sempre fare comodo
Lascio le porte aperte ad ulteriori sviluppi.