2011-09-15 10 views
18

Utilizzo Web Deploy per il pacchetto e la distribuzione di siti Web per il mio prodotto. In particolare, ho due diversi progetti nella mia soluzione. Uso questo metodo per la distribuzione.Utilizzo di MsBuild per generare manifest MsDeploy personalizzato (destinazione pacchetto)

Ho un terzo progetto nella soluzione (un servizio Windows) che deve anche essere installato sul server web.

So che posso scrivere un manifest personalizzato (per i provider dirPath, filePath e runCommand) e chiamare direttamente MsDeploy per distribuirlo. Ma mi piacerebbe sfruttare le attività esistenti di MsBuild per pacchettizzare il mio servizio, se possibile.

vedo che è possibile fare un po 'di personalizzazione del file manifesto tramite obiettivi MSBuild:

http://social.msdn.microsoft.com/Forums/en/msbuild/thread/1044058c-f762-456b-8a68-b0863027ce47

In particolare utilizzando la voce di MsDeploySourceManifest.

Dopo frugando tra le file .targets appropriati, sembra che sia contentPath o iisApp otterrà aggiunto alla mia manifesta se uso il bersaglio Package. Idealmente mi piacerebbe solo copiare un assembly (o directory), eventualmente impostare ACL ed eseguire installutil.exe sul servizio.

È possibile personalizzare completamente il manifest generato dal target , modificando il file csproj?

In caso contrario, c'è un modo semplice per creare un nuovo target che faccia l'equivalente a Package, ma permettimi di sputare un manifest completamente personalizzato?

+0

Hai ricevuto una risposta? – musica

+0

@Graci: l'ho fatto. Sto finendo l'oggetto di lavoro per questo durante questa settimana, e posterò una risposta dopo che tutto funzionerà. I concetti chiave sono la creazione di un file '.targets' personalizzato, utilizzare i target personalizzati per aggiungere le voci del provider' runCommand' per eseguire file batch personalizzati (per arrestare/disinstallare il servizio e installarlo/avviarlo), aggiungere Parametri personalizzati. file xml al progetto e imposta alcuni flag, come 'IncludeIisSettingsOnPublish = False' e' IncludeIisSettingsOnPublish = False'. Oh, e anche l'estensione di trasformazione non web di SlowCheetah è stata di aiuto. –

+0

@Merlyn: Sarebbe fantastico se tu trovassi il tempo di condividere la tua soluzione, dal tuo ultimo commento sembra che tu abbia capito bene. –

risposta

16

Non ho ancora una scrittura completa per le persone che cercano di imparare come funziona, ma ora ho una descrizione su come realizzare almeno questo obiettivo.

http://thehappypath.net/2011/11/21/using-msdeploy-for-windows-services/

(edit:. Collegamento è morto per ora Fatemi sapere se siete interessati e vi posso postare altrove).

La mia guida passa attraverso questi passaggi complessivi:

  • Assicurarsi che il servizio stesso si avvia dopo l'installazione (non determinante, ma più facile da affrontare)
  • aggiungere il file Microsoft.WebApplication.targets al progetto, anche se non hai un progetto web. Ciò abilita la destinazione MsBuild Package.
  • Aggiungi un personalizzato file al progetto .targets che costruisce un pacchetto personalizzato MsBuild manifesta
  • aggiungere alcuni script batch al progetto per fermare/disinstallare e installare il servizio
  • Aggiungere un file Parameters.xml per sostenere il cambiamento indirizzare la directory di distribuzione un po 'più facilmente
  • Impostare l'app.trasformazioni di configurazione utilizzando the SlowCheetah Visual Studio addon

Poi si può impacchettare il progetto con questa riga di comando:

msbuild MyProject.csproj /t:Package /p:Configuration=Debug 

È possibile distribuire il pacchetto risultante con questa riga di comando:

MyService.Deploy.cmd /Y /M:mywebserver -allowUntrusted 

La parte più privi di documenti di questo (fatta eccezione per la mia guida) sta creando il manifest personalizzato. Ecco un dump del mio file corrente (nota, è ancora un po 'buggy, ma può essere risolto - Vedi questa domanda: MsDeploy remoting executing manifest twice - e prova a continuare a usare solo file batch diretti per runCommand).

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" DefaultTargets="Build" 
     xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <!-- This file must be included before Microsoft.Web.Publishing.targets so we can hook into BeforeAddIisSettingAndFileContentsToSourceManifest --> 

    <PropertyGroup> 

    <!-- Include our targets --> 
    <IncludeStopServiceCommand>True</IncludeStopServiceCommand> 
    <IncludeSetCustomAclsProvider>True</IncludeSetCustomAclsProvider> 
    <IncludeInstallServiceCommand>True</IncludeInstallServiceCommand> 
    <IncludeMoveAppConfigToCorrectPackagePath>True</IncludeMoveAppConfigToCorrectPackagePath> 

    <!-- Uncomment to enable more verbose MsBuild logging --> 
    <!-- <EnablePackageProcessLoggingAndAssert>True</EnablePackageProcessLoggingAndAssert> --> 

    <!-- Enable web.config transform, but hack it to work for app.config --> 
    <ProjectConfigFileName>app.config</ProjectConfigFileName> 
    <TransformWebConfigEnabled>True</TransformWebConfigEnabled> 
    <UseParameterizeToTransformWebConfig>True</UseParameterizeToTransformWebConfig> 

    <!-- Enable web project packaging, but hack it to work for non-web app --> 
    <DeployAsIisApp>False</DeployAsIisApp> 
    <IncludeIisSettingsOnPublish>False</IncludeIisSettingsOnPublish> 
    <IncludeSetAclProviderOnDestination>False</IncludeSetAclProviderOnDestination> 
    <DisableAllVSGeneratedMSDeployParameter>True</DisableAllVSGeneratedMSDeployParameter> 

    <!-- Insert our custom targets into correct places in build process --> 
    <BeforeAddIisSettingAndFileContentsToSourceManifest Condition="'$(BeforeAddIisSettingAndFileContentsToSourceManifest)'==''"> 
     $(BeforeAddIisSettingAndFileContentsToSourceManifest); 
     AddStopServiceCommand; 
    </BeforeAddIisSettingAndFileContentsToSourceManifest> 

    <AfterAddIisSettingAndFileContentsToSourceManifest Condition="'$(AfterAddIisSettingAndFileContentsToSourceManifest)'==''"> 
     $(AfterAddIisSettingAndFileContentsToSourceManifest); 
     AddSetCustomAclsProvider; 
     AddInstallServiceCommand; 
    </AfterAddIisSettingAndFileContentsToSourceManifest> 

    <OnAfterCopyAllFilesToSingleFolderForPackage Condition="'$(OnAfterCopyAllFilesToSingleFolderForPackage)'==''"> 
     $(OnAfterCopyAllFilesToSingleFolderForPackage); 
     MoveAppConfigToCorrectPackagePath; 
    </OnAfterCopyAllFilesToSingleFolderForPackage> 

    </PropertyGroup> 

    <!-- Custom targets --> 
    <Target Name="AddStopServiceCommand" Condition="'$(IncludeStopServiceCommand)'=='true'"> 
    <Message Text="Adding runCommand to stop the running Service" /> 
    <ItemGroup> 

     <MsDeploySourceManifest Include="runCommand"> 
     <path>$(_MSDeployDirPath_FullPath)\bin\servicestop.bat</path> 
     <waitInterval>20000</waitInterval> 
     <AdditionalProviderSettings>waitInterval</AdditionalProviderSettings> 
     </MsDeploySourceManifest> 

    </ItemGroup> 
    </Target> 

    <Target Name="AddSetCustomAclsProvider" Condition="'$(IncludeSetCustomAclsProvider)'=='true'"> 
    <ItemGroup> 

     <MsDeploySourceManifest Include="setAcl"> 
     <Path>$(_MSDeployDirPath_FullPath)</Path> 
     <setAclUser>LocalService</setAclUser> 
     <setAclAccess>FullControl</setAclAccess> <!-- Todo: Reduce these permissions --> 
     <setAclResourceType>Directory</setAclResourceType> 
     <AdditionalProviderSettings>setAclUser;setAclAccess;setAclResourceType</AdditionalProviderSettings> 
     </MsDeploySourceManifest> 

    </ItemGroup> 
    </Target> 

    <Target Name="AddInstallServiceCommand" Condition="'$(IncludeInstallServiceCommand)'=='true'"> 
    <Message Text="Adding runCommand to install the Service" /> 
    <ItemGroup> 

     <MsDeploySourceManifest Include="runCommand"> 
     <path>cmd.exe /c $(_MSDeployDirPath_FullPath)\bin\serviceinstall.bat</path> 
     <waitInterval>20000</waitInterval> 
     <dontUseCommandExe>false</dontUseCommandExe> 
     <AdditionalProviderSettings>waitInterval;dontUseCommandExe</AdditionalProviderSettings> 
     </MsDeploySourceManifest> 

    </ItemGroup> 
    </Target> 

    <Target Name="MoveAppConfigToCorrectPackagePath" 
      Condition="'$(IncludeMoveAppConfigToCorrectPackagePath)'=='true'"> 
    <PropertyGroup> 
     <OriginalAppConfigFilename>$(_PackageTempDir)\App.Config</OriginalAppConfigFilename> 
     <TargetAppConfigFilename>$(_PackageTempDir)\bin\$(TargetFileName).config</TargetAppConfigFilename> 
    </PropertyGroup> 

    <Copy SourceFiles="$(OriginalAppConfigFilename)" DestinationFiles="$(TargetAppConfigFilename)" 
      Condition="Exists($(OriginalAppConfigFilename))" /> 
    <Delete Files="$(OriginalAppConfigFilename)" 
      Condition="Exists($(OriginalAppConfigFilename))" /> 
    </Target> 

</Project> 
+0

Perché stai includendo nei passaggi elenca i loro valori originali, quando prima stai affermando che sono vuoti? È davvero necessario a causa di qualcosa di orribile? Voglio dire, alcune delle proprietà sembrano ' $ (prop); estensione ', quindi sono entrambi 'use if not set' e 'injection, not overriding'. Il tuo campione si attacca solo se non è già collegato a nessun altro, e allo stesso tempo cerca di preservare il contenuto originale (supposto che sia vuoto direttamente prima di esso). Penserei che o quelle condizioni, o il comportamento 'concat' non è necessario. – quetzalcoatl

+0

Comunque, ottimo lavoro! Ho appena trovato patch/estensioni simili prima di trovare il tuo frammento, quindi probabilmente è l'unico modo. Btw. Ho anche trovato il 'TransformWebConfigEnabled' per avere' true' di default, quindi probabilmente può anche essere tagliato. Btw2. hai provato la parametrizzazione di app.config? Non ci sono problemi con l'applicazione dei valori di 'SetParameters.xml' a causa del fatto che' webconfig/appconfig' è stato spostato e rinominato? – quetzalcoatl

+0

Hm .. Sì, sono abbastanza sicuro che ci sarà un problema, dato che c'è un chiaro riferimento al vecchio 'App.config' nel file 'parameters.xml' all'interno del pacchetto.Penso che siano necessarie alcune correzioni aggiuntive per il target "ImportParametersFiles' o vicino a quello. – quetzalcoatl