ClickOnce, per certe cose, è una tecnologia fantastica, se però siete in un ambiente un po’ complesso e avete i classici ambienti di Sviluppo, Test, Produzione e chi più ne ha più ne metta scoprite che Visual Studio non digerisce questa cosa neanche a spingere…
Ci sono un po’ di soluzioni con pregi e difetti, partiamo da Visual Studio e poi vediamo come affronta la cosa ClickOnce. La situazione classica è la necessità di avere file di configurazione diversi per ambiente diverso, classicamente ad esempio cambia la connection string al db, quello che possiamo fare è:
image
nella solution creiamo una struttura di cartelle in cui inserire i vari file di configurazione, ogni cartella dentro “Copnfig Files” ha lo stesso nome di una configurazione della solution, c’è poi direttamente un file app.config dentro “Config Files” che serve da fallback nel caso in cui non esista un file specifico per una configurazione.
A questo punto possiamo scegliere una configurazione per la nostra solution:
image
e provare a compilare, naturalmente non succede un bel nulla :-D… speravate fosse così facile. In realtà non è poi molto difficile, andiamo nelle proprietà del progetto e nei Post Build Event mettiamo qualcosa del tipo:
if exist "$(ProjectDir)Properties\Config Files\$(ConfigurationName)\app.config" (
    copy "$(ProjectDir)Properties\Config Files\$(ConfigurationName)\app.config" "$(ProjectDir)$(OutDir)$(TargetName).config" /Y
) else (
    copy "$(ProjectDir)Properties\Config Files\app.config" "$(ProjectDir)$(OutDir)$(TargetName).config" /Y
)

che altro non fa che controllare se un file per una data configurazione esiste altrimenti usa il file di fallback. La cosa è abbastanza semplice e non è certo una novità, ci sono molti post che ne parlano.
Veniamo adesso a ClickOnce… “il simpaticone” non digerisce molto questa cosa, o meglio non si lamenta ma non funziona perchè “il simpaticone” non prende il file di configurazione che trova nella directory di output del progetto ma bensì quello che sta nella root del progetto di Visual Studio…ma si facesse gli affari suoi…
Una soluzione c’è, è molto bella, fa un sacco di belle cose ma un po’ troppo complessa da gestire, inoltre è pensata per Visual Studio 2005 e lo schema del deploy di ClickOnce di Visual Studio 2008 SP1 è un po’ diverso e quindi va adattata a suon di “prova e sbaglia” perchè c’è poca se non nulla documentazione, ci apre anche alla magagna di dover star dietro alle evoluzioni future dello schema.
Ma… si può fare ed è abbastanza banale, prendiamo il nostro post build event e lo modifichiamo così:
if exist "$(ProjectDir)Properties\Config Files\$(ConfigurationName)\app.config" (
    copy "$(ProjectDir)Properties\Config Files\$(ConfigurationName)\app.config" "$(ProjectDir)app.config" /Y
) else (
    copy "$(ProjectDir)Properties\Config Files\app.config" "$(ProjectDir)app.config" /Y
)

con l’accortezza di spostarlo dai Post Build Event ai Pre Build Event, quello che succede è che il file di configurazione che sta nella root del progetto viene sostituito prima della compilazione con 2 effetti:
  • nella directory di output del progetto ci troviamo il file che ci aspettiamo, per l’ambiente giusto;
  • cambiando direttamente il file config del progetto “il simpaticone” (aka ClickOnce) prende il file giusto;
Unica accortezza, se usate un sistema di source control, è quella di escludere dal source control il file app.config nella root dell’applicazione in modo da evitare fallimenti della build per il semplice fatto che il file sia in checkin.
C’è anche un’altra soluzione: costruire un task di MS Build… ma il gioco non vale la candela.
.m