Informazioni sul file di progetto

di Jason Lee

i file di progetto Microsoft Build Engine (MSBuild) si trovano al centro del processo di compilazione e distribuzione. Questo argomento inizia con una panoramica concettuale di MSBuild e del file di progetto. Descrive i componenti chiave che verranno visualizzati quando si lavora con i file di progetto e funziona con un esempio di come è possibile usare i file di progetto per distribuire applicazioni reali.

Contenuto dell'esercitazione:

  • Come MSBuild usa i file di progetto MSBuild per compilare progetti.
  • Modalità di integrazione di MSBuild con tecnologie di distribuzione, ad esempio lo strumento di distribuzione Web Internet Information Services (IIS) (Distribuzione Web).
  • Come comprendere i componenti chiave di un file di progetto.
  • Come usare i file di progetto per compilare e distribuire applicazioni complesse.

MSBuild e il file di progetto

Quando si creano e si compilano soluzioni in Visual Studio, Visual Studio usa MSBuild per compilare ogni progetto nella soluzione. Ogni progetto di Visual Studio include un file di progetto MSBuild, con un'estensione di file che riflette il tipo di progetto, ad esempio un progetto C# (con estensione csproj), un progetto di Visual Basic.NET (con estensione vbproj) o un progetto di database (con estensione dbproj). Per compilare un progetto, MSBuild deve elaborare il file di progetto associato al progetto. Il file di progetto è un documento XML contenente tutte le informazioni e le istruzioni richieste da MSBuild per compilare il progetto, ad esempio il contenuto da includere, i requisiti della piattaforma, le informazioni sul controllo delle versioni, le impostazioni del server Web o del server di database e le attività da eseguire.

I file di progetto MSBuild si basano su MSBuild XML Schema e di conseguenza il processo di compilazione è completamente aperto e trasparente. Inoltre, non è necessario installare Visual Studio per usare il motore MSBuild. Il file eseguibile MSBuild.exe fa parte di .NET Framework ed è possibile eseguirlo da un prompt dei comandi. Gli sviluppatori possono creare file di progetto MSBuild personalizzati, usando lo schema XML MSBuild, per imporre un controllo sofisticato e granulare sul modo in cui vengono compilati e distribuiti i progetti. Questi file di progetto personalizzati funzionano esattamente come i file di progetto generati automaticamente da Visual Studio.

Nota

È anche possibile usare i file di progetto MSBuild con il servizio Team Build in Team Foundation Server (TFS). Ad esempio, è possibile usare i file di progetto in scenari di integrazione continua (CI) per automatizzare la distribuzione in un ambiente di test quando viene archiviato un nuovo codice. Per altre informazioni, vedere Configurazione di Team Foundation Server per la distribuzione Web automatizzata.

Convenzioni di denominazione dei file di progetto

Quando si creano file di progetto personalizzati, è possibile usare qualsiasi estensione di file desiderata. Tuttavia, per semplificare la comprensione delle soluzioni, è consigliabile usare queste convenzioni comuni:

  • Usare l'estensione proj quando si crea un file di progetto che compila progetti.
  • Usare l'estensione targets quando si crea un file di progetto riutilizzabile da importare in altri file di progetto. I file con estensione targets in genere non compilano nulla, contengono semplicemente istruzioni che è possibile importare nei file con estensione proj.

Integrazione con le tecnologie di distribuzione

Se sono stati usati progetti di applicazioni Web in Visual Studio 2010, ad esempio ASP.NET applicazioni Web e ASP.NET applicazioni Web MVC, questi progetti includono il supporto predefinito per la creazione di pacchetti e la distribuzione dell'applicazione Web in un ambiente di destinazione. Le pagine Proprietà per questi progetti includono le schede Package/Publish Web e Package/Publish SQL che è possibile usare per configurare la modalità di creazione di pacchetti e distribuzione dei componenti dell'applicazione. Verrà visualizzata la scheda Web Pacchetto/Pubblicazione :

Scheda Web Pacchetto/Pubblicazione

La tecnologia sottostante alla base di queste funzionalità è nota come Pipeline di pubblicazione Web (WPP). Il WPP riunisce essenzialmente MSBuild e Distribuzione Web per fornire un processo completo di compilazione, pacchetto e distribuzione per le applicazioni Web.

La buona notizia è che è possibile sfruttare i punti di integrazione forniti dal WPP quando si creano file di progetto personalizzati per i progetti Web. È possibile includere le istruzioni di distribuzione nel file di progetto, che consente di compilare i progetti, creare pacchetti di distribuzione Web e installare questi pacchetti in server remoti tramite un singolo file di progetto e una singola chiamata a MSBuild. È anche possibile chiamare qualsiasi altro eseguibile come parte del processo di compilazione. Ad esempio, è possibile eseguire lo strumento da riga di comando VSDBCMD.exe per distribuire un database da un file di schema. Nel corso di questo argomento si vedrà come sfruttare queste funzionalità per soddisfare i requisiti degli scenari di distribuzione aziendali.

Nota

Per altre informazioni sul funzionamento del processo di distribuzione dell'applicazione Web, vedere ASP.NET Panoramica della distribuzione del progetto di applicazione Web.

Anatomia di un file di progetto

Prima di esaminare il processo di compilazione in modo più dettagliato, è consigliabile acquisire familiarità con la struttura di base di un file di progetto MSBuild. In questa sezione viene fornita una panoramica degli elementi più comuni che verranno visualizzati durante la revisione, la modifica o la creazione di un file di progetto. In particolare, si apprenderà:

  • Come usare le proprietà per gestire le variabili per il processo di compilazione.
  • Come usare gli elementi per identificare gli input per il processo di compilazione, ad esempio i file di codice.
  • Come usare destinazioni e attività per fornire istruzioni di esecuzione a MSBuild, usando proprietà ed elementi definiti altrove nel file di progetto.

Viene illustrata la relazione tra gli elementi chiave in un file di progetto MSBuild:

Relazione tra gli elementi chiave in un file di progetto MSBuild.

Elemento Project

L'elemento Project è l'elemento radice di ogni file di progetto. Oltre a identificare lo schema XML per il file di progetto, l'elemento Project può includere attributi per specificare i punti di ingresso per il processo di compilazione. Nella soluzione di esempio Contact Manager, ad esempio, il file Publish.proj specifica che la compilazione deve iniziare chiamando la destinazione denominata FullPublish.

<Project ToolsVersion="4.0" DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
</Project>

Proprietà e condizioni

Un file di progetto in genere deve fornire molte informazioni diverse per compilare e distribuire correttamente i progetti. Queste informazioni possono includere nomi di server, stringhe di connessione, credenziali, configurazioni di compilazione, percorsi di file di origine e di destinazione e qualsiasi altra informazione da includere per supportare la personalizzazione. In un file di progetto le proprietà devono essere definite all'interno di un elemento PropertyGroup . Le proprietà di MSBuild sono costituite da coppie chiave-valore. All'interno dell'elemento PropertyGroup , il nome dell'elemento definisce la chiave della proprietà e il contenuto dell'elemento definisce il valore della proprietà. Ad esempio, è possibile definire proprietà denominate ServerName e ConnectionString per archiviare un nome server statico e stringa di connessione.

<PropertyGroup>    
   <ServerName>FABRIKAM\TEST1</ServerName>
   <ConnectionString>
     Data Source=FABRIKAM\TESTDB;InitialCatalog=ContactManager,...
   </ConnectionString>
</PropertyGroup>

Per recuperare un valore della proprietà, usare il formato $(PropertyName). Ad esempio, per recuperare il valore della proprietà ServerName , digitare:

$(ServerName)

Nota

Di seguito sono riportati esempi di come e quando usare i valori delle proprietà più avanti in questo argomento.

L'incorporamento delle informazioni come proprietà statiche in un file di progetto non è sempre l'approccio ideale per la gestione del processo di compilazione. In molti scenari è necessario ottenere le informazioni da altre origini o consentire all'utente di fornire le informazioni dal prompt dei comandi. MSBuild consente di specificare qualsiasi valore della proprietà come parametro della riga di comando. Ad esempio, l'utente può fornire un valore per ServerName quando esegue MSBuild.exe dalla riga di comando.

msbuild.exe Publish.proj /p:ServerName=FABRIKAM\TESTWEB1

Nota

Per altre informazioni sugli argomenti e sulle opzioni che è possibile usare con MSBuild.exe, vedere Informazioni di riferimento sulla riga di comando di MSBuild.

È possibile usare la stessa sintassi delle proprietà per ottenere i valori delle variabili di ambiente e le proprietà predefinite del progetto. Molte proprietà di uso comune sono definite automaticamente ed è possibile usarle nei file di progetto includendo il nome del parametro pertinente. Ad esempio, per recuperare la piattaforma di progetto corrente, ad esempio x86 o AnyCpu, è possibile includere il riferimento alla proprietà $(Platform) nel file di progetto. Per altre informazioni, vedere Macro per comandi e proprietà di compilazione, proprietà comuni del progetto MSBuild e proprietà riservate.

Le proprietà vengono spesso usate in combinazione con le condizioni. La maggior parte degli elementi MSBuild supporta l'attributo Condition , che consente di specificare i criteri in base ai quali MSBuild deve valutare l'elemento. Si consideri ad esempio questa definizione di proprietà:

<PropertyGroup>
   <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
   ...
</PropertyGroup>

Quando MSBuild elabora questa definizione di proprietà, verifica innanzitutto se è disponibile un valore della proprietà $(OutputRoot). Se il valore della proprietà è vuoto, ovvero l'utente non ha fornito un valore per questa proprietà, la condizione restituisce true e il valore della proprietà è impostato su .. \Publish\Out. Se l'utente ha fornito un valore per questa proprietà, la condizione restituisce false e il valore della proprietà statica non viene utilizzato.

Per altre informazioni sui diversi modi in cui è possibile specificare le condizioni, vedere Condizioni di MSBuild.

Elementi e gruppi di elementi

Uno dei ruoli importanti del file di progetto consiste nel definire gli input per il processo di compilazione. In genere, questi input sono file, file di codice, file di configurazione, file di comando e qualsiasi altro file che è necessario elaborare o copiare come parte del processo di compilazione. Nello schema del progetto MSBuild questi input sono rappresentati dagli elementi Item . In un file di progetto gli elementi devono essere definiti all'interno di un elemento ItemGroup . Proprio come gli elementi Property , è possibile assegnare un nome a un elemento Item come si preferisce. È tuttavia necessario specificare un attributo Include per identificare il file o il carattere jolly rappresentato dall'elemento.

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

Specificando più elementi Item con lo stesso nome, si crea in modo efficace un elenco denominato di risorse. Un buon modo per verificarlo in azione consiste nell'esaminare uno dei file di progetto creati da Visual Studio. Ad esempio, il file ContactManager.Mvc.csproj nella soluzione di esempio include molti gruppi di elementi, ognuno con diversi elementi denominati in modo identico.

<ItemGroup>
   <Reference Include="Microsoft.CSharp" />
   <Reference Include="System.Runtime.Serialization" />
   <Reference Include="System.ServiceModel" />
   ...
</ItemGroup>
<ItemGroup>
   <Compile Include="Controllers\AccountController.cs" />
   <Compile Include="Controllers\ContactsController.cs" />
   <Compile Include="Controllers\HomeController.cs" />
   ...
</ItemGroup>
<ItemGroup>
   <Content Include="Content\Custom.css" />
   <Content Include="CreateDatabase.sql" />
   <Content Include="DropDatabase.sql" />
   ...
</ItemGroup>

In questo modo, il file di progetto indica a MSBuild di costruire elenchi di file che devono essere elaborati nello stesso modo. L'elenco Riferimenti include assembly che devono essere applicati per una compilazione corretta, l'elenco Compilazione include file di codice che devono essere compilati e l'elenco Contenuto include risorse che devono essere copiate senza modifica. Si esaminerà il modo in cui il processo di compilazione fa riferimento e usa questi elementi più avanti in questo argomento.

Gli elementi item possono includere anche elementi figlio ItemMetadata . Si tratta di coppie chiave-valore definite dall'utente e essenzialmente rappresentano proprietà specifiche di tale elemento. Ad esempio, molti elementi dell'elemento Compile nel file di progetto includono elementi figlio DependentUpon .

<Compile Include="Global.asax.cs">
   <DependentUpon>Global.asax</DependentUpon>
</Compile>

Nota

Oltre ai metadati degli elementi creati dall'utente, a tutti gli elementi vengono assegnati vari metadati comuni durante la creazione. Per altre informazioni, vedere Metadati noti degli elementi.

È possibile creare elementi ItemGroup all'interno dell'elemento Project a livello radice o all'interno di elementi Target specifici. Gli elementi ItemGroup supportano anche gli attributi Condition , che consentono di personalizzare gli input per il processo di compilazione in base a condizioni come la configurazione del progetto o la piattaforma.

Destinazioni e attività

Nello schema MSBuild un elemento Task rappresenta una singola istruzione di compilazione (o attività). MSBuild include una moltitudine di attività predefinite. Ad esempio:

  • L'attività Copia copia i file in un nuovo percorso.
  • L'attività Csc richiama il compilatore Visual C#.
  • L'attività Vbc richiama il compilatore Visual Basic.
  • L'attività Exec esegue un programma specificato.
  • L'attività Messaggio scrive un messaggio in un logger.

Nota

Per informazioni dettagliate sulle attività disponibili, vedere Informazioni di riferimento sulle attività di MSBuild. Per altre informazioni sulle attività, tra cui come creare attività personalizzate, vedere Attività di MSBuild.

Le attività devono essere sempre contenute negli elementi target . Un elemento Target è un set di una o più attività eseguite in sequenza e un file di progetto può contenere più destinazioni. Quando si vuole eseguire un'attività o un set di attività, richiamare la destinazione che li contiene. Si supponga, ad esempio, di avere un file di progetto semplice che registra un messaggio.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

È possibile richiamare la destinazione dalla riga di comando usando l'opzione /t per specificare la destinazione.

msbuild.exe Publish.proj /t:LogMessage

In alternativa, è possibile aggiungere un attributo DefaultTargets all'elemento Project per specificare le destinazioni da richiamare.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
         DefaultTargets="FullPublish">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

In questo caso, non è necessario specificare la destinazione dalla riga di comando. È sufficiente specificare il file di progetto e MSBuild richiamerà la destinazione FullPublish .

msbuild.exe Publish.proj

Sia le destinazioni che le attività possono includere attributi Condition . Di conseguenza, è possibile scegliere di omettere intere destinazioni o singole attività se vengono soddisfatte determinate condizioni.

In generale, quando si creano attività e destinazioni utili, è necessario fare riferimento alle proprietà e agli elementi definiti altrove nel file di progetto:

  • Per utilizzare un valore della proprietà, digitare $(PropertyName), dove PropertyName è il nome dell'elemento Property o il nome del parametro.
  • Per utilizzare un elemento, digitare @(ItemName), dove ItemName è il nome dell'elemento Item .

Nota

Tenere presente che se si creano più elementi con lo stesso nome, si sta creando un elenco. Al contrario, se si creano più proprietà con lo stesso nome, l'ultimo valore della proprietà specificato sovrascriverà tutte le proprietà precedenti con lo stesso nome. Una proprietà può contenere solo un singolo valore.

Ad esempio, nel file Publish.proj nella soluzione di esempio esaminare la destinazione BuildProjects .

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"           
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
</Target>

In questo esempio è possibile osservare questi punti chiave:

  • Se il parametro BuildingInTeamBuild viene specificato e ha un valore true, non verrà eseguita alcuna attività all'interno di questa destinazione.

  • La destinazione contiene una singola istanza dell'attività MSBuild . Questa attività consente di compilare altri progetti MSBuild.

  • L'elemento ProjectsToBuild viene passato all'attività. Questo elemento può rappresentare un elenco di file di progetto o di soluzione, tutti definiti dagli elementi elemento ProjectsToBuild all'interno di un gruppo di elementi. In questo caso, l'elemento ProjectsToBuild fa riferimento a un singolo file di soluzione.

    <ItemGroup>
       <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
    </ItemGroup>
    
  • I valori delle proprietà passati all'attività MSBuild includono parametri denominati OutputRoot e Configuration. Questi valori vengono impostati su valori di parametro, se specificati o valori di proprietà statici, se non lo sono.

    <PropertyGroup>
       ... 
       <Configuration Condition=" '$(Configuration)'=='' ">Release
       </Configuration>
       <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\
       </OutputRoot>
       ...
    </PropertyGroup>
    

È anche possibile notare che l'attività MSBuild richiama una destinazione denominata Build. Si tratta di una delle diverse destinazioni predefinite ampiamente usate nei file di progetto di Visual Studio e sono disponibili nei file di progetto personalizzati, ad esempio Compilazione, Pulizia, Ricompilazione e Pubblicazione. Altre informazioni sull'uso di destinazioni e attività per controllare il processo di compilazione e sull'attività MSBuild in particolare, più avanti in questo argomento.

Nota

Per altre informazioni sulle destinazioni, vedere Destinazioni MSBuild.

Suddivisione di file di progetto per supportare più ambienti

Si supponga di voler essere in grado di distribuire una soluzione in più ambienti, ad esempio server di test, piattaforme di staging e ambienti di produzione. La configurazione può variare notevolmente tra questi ambienti, non solo in termini di nomi di server, stringhe di connessione e così via, ma anche potenzialmente in termini di credenziali, impostazioni di sicurezza e molti altri fattori. Se è necessario eseguire questa operazione regolarmente, non è veramente opportuno modificare più proprietà nel file di progetto ogni volta che si cambia l'ambiente di destinazione. Né è una soluzione ideale per richiedere un elenco infinito di valori di proprietà da fornire al processo di compilazione.

Fortunatamente c'è un'alternativa. MSBuild consente di suddividere la configurazione di compilazione tra più file di progetto. Per vedere come funziona, nella soluzione di esempio si noti che sono presenti due file di progetto personalizzati:

  • Publish.proj, che contiene proprietà, elementi e destinazioni comuni a tutti gli ambienti.
  • Env-Dev.proj, che contiene proprietà specifiche di un ambiente di sviluppo.

Si noti ora che il file Publish.proj include un elemento Import , immediatamente sotto il tag Project di apertura.

<Import Project="$(TargetEnvPropsFile)"/>

L'elemento Import viene usato per importare il contenuto di un altro file di progetto MSBuild nel file di progetto MSBuild corrente. In questo caso, il parametro TargetEnvPropsFile fornisce il nome file del file di progetto da importare. È possibile specificare un valore per questo parametro quando si esegue MSBuild.

msbuild.exe Publish.proj /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

Questo unisce in modo efficace il contenuto dei due file in un singolo file di progetto. Usando questo approccio, è possibile creare un file di progetto contenente la configurazione di compilazione universale e più file di progetto supplementari contenenti proprietà specifiche dell'ambiente. Di conseguenza, l'esecuzione di un comando con un valore di parametro diverso consente di distribuire la soluzione in un ambiente diverso.

L'esecuzione di un comando con un valore di parametro diverso consente di distribuire la soluzione in un ambiente diverso.

La suddivisione dei file di progetto in questo modo è una procedura consigliata da seguire. Consente agli sviluppatori di eseguire la distribuzione in più ambienti eseguendo un singolo comando, evitando la duplicazione delle proprietà di compilazione universali in più file di progetto.

Nota

Per indicazioni su come personalizzare i file di progetto specifici dell'ambiente per i propri ambienti server, vedere Configurazione delle proprietà di distribuzione per un ambiente di destinazione.

Conclusione

In questo argomento è stata fornita un'introduzione generale ai file di progetto MSBuild e viene illustrato come creare file di progetto personalizzati per controllare il processo di compilazione. Ha anche introdotto il concetto di suddivisione dei file di progetto in istruzioni di compilazione universali e proprietà di compilazione specifiche dell'ambiente, per semplificare la compilazione e la distribuzione di progetti in più destinazioni.

L'argomento successivo, Informazioni sul processo di compilazione, fornisce altre informazioni su come usare i file di progetto per controllare la compilazione e la distribuzione esaminando la distribuzione di una soluzione con un livello realistico di complessità.

Altre informazioni

Per un'introduzione più approfondita ai file di progetto e al WPP, vedere Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build by Sayed Ibrahim Hashimi and William Bartholomew, ISBN: 978-0-7356-4524-0.