11 November 2010 HowTo, MSBuild, MSDeploy Robert Muehsig

image

In meinen letzten Blogpost beschrieb ich, was man mit MSBuild anstellen kann. Mit MSBuild kann man auch mit ein paar Tricks ein nettes Deployment Package zusammenbauen. Microsoft hat mit dem Release von VS2010 ein neues Tool ins rennen geschickt: MSDeploy. In dem Blogpost geht es darum, was MSDeploy ist und wie man es mit MSBuild zusammen einsetzen kann.

Big Picture von MSDeploy

Beginnen wir kurz mit dem großen Bild von MSDeploy. Ziel ist es ein Deployment Package zusammen zu bauen um das Ausliefern der Software zu vereinfachen. Dafür gibt es diverse Provider, welche z.B. die Datenbank oder die eigentlichen ASP.NET Files in ein Package zusammen packt. Dieses Package kann man dann über MSDeploy recht einfach publishen. Dabei muss auf dem Server ebenfalls MSDeploy installiert sein.

Ich verweise an diese Stelle auf den Blogpost von ScottGu sowie den Blog von Vishal Joshi (gefühlt ist es DER Entwickler hinter MSDeploy).

image

Der Reiz an MSDeploy: Es ist recht einfach neue Updates einzuspielen. Das kann z.B. von der Entwicklermaschine mit Visual Studio sein oder ein Buildserver über ein Buildscript.

MSDeploy auf dem Server

Über den Web Platform Installer lässt sich MSDeploy installieren (siehe ScottGus Post). Wichtig ist noch: Die Port von MSDeploy muss auch in der Firewall freigeschalten werden. Alle anderen Details erfahrt ihr entweder in ScottGus Post oder auf IIS.NET hier, hier und hier.

Meine bisherigen Deployansätze

Bislang hatte ich über MSBuild eine Solution gebaut und das "_PublishedWebsites” Verzeichnis genutzt. Im letzten Blogpost ging es ja dann um die Web.config Transformierung. Allerdings geht das alles auch etwas eleganter.

MSDeploy ist momentan auf Webanwendungen ausgelegt. Daher muss man sich über das Deployment und Packaging von Windows Services etc. trotzdem noch Gedanken machen ;)

Einfaches Beispiel

image

In meinem einfachen Beispiel habe ich eine MVC WebApp und diese möchte ich nun in ein Deployment Package haben.

Variante A) Man macht alles über Visual Studio. Rechtsklick auf das Projekt und dann "Build Deployment Package”. Wenn man alleine vor sich hinwerkelt geht das noch. Ich finde allerdings man sollte wenigstens ein Build auch scriptgesteuert aufrufen können. Spätestens wenn man ein Buildserver einsetzen möchte führt kein Weg daran vorbei.

Daher Variante b) Wir schreiben uns ein kleines MSBuild Script. Der OutPut wird am Ende identisch mit der Variante A sein - nur dass wir es in ein Script ausgelagert haben.

In den Deployment Settings können wir noch die IIS Settings vordefinieren:

image

Diese Angaben können aber auch über Parameter später gesetzt werden. Wir gehen mal davon aus, dass diese Wert in diesen Settings gesetzt werden. Die Seite die ich dort angebe sollte im IIS auf dem Zielrechner auch schon angelegt sein. Ich bin mir jetzt nicht sicher was passiert, wenn diese nicht da ist ;)

Jetzt zum eigentlichen Script.

Build.targets

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run">
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
   <PropertyGroup>
	<OutDir>$(MSBuildStartupDirectory)\OutDir\</OutDir>
   </PropertyGroup>
	<Target Name="Run">
	<Message Text="Run called." />
			<MSBuild Projects="MSDeployMSBuild.Web\MSDeployMSBuild.Web.csproj"
            Targets="Package"
			Properties="PackageLocation=$(OutDir)\MSDeploy\Package.zip;
						_PackageTempDir=C:\Temp\Web"/>
	</Target>

</Project>
 

Am wichtigsten ist hier eigentlich Zeile 8. Hier rufe ich das Package Target auf. Damit wird MSDeploy angestoßen und es wird auch automatisch eine Web.config Transformation durchgeführt. Als Property geb ich noch die PackageLocation mit sowie eine Hilfe Variable namens "_PackageTempDir”.

Als Ergebnis kommt sowas raus eines "Build Deployment Packge” oder von diesem MSBuild kommt sowas raus:

image

Wenn man jetzt das _PackageTempDir nicht setzt steht in der Package.SourceManifest.xml allerdings der komplette Pfad aus dem gebaut wurde. Das will ich nicht und darum setz ich dort einen x-beliebigen anderen ein. Dieser Pfad scheint auch keine Auswirkung auf das Deployment später zu haben. Es sieht meiner Meinung nach aber etwas komisch aus ;)

Wenn man nicht direkt das Projekt bauen will, sondern die Solution:

In den vergangen Blogposts habe ich immer die gesamte Solution gebaut. Das geht auch, dafür muss man bei der Solution diese Parameter mitgeben:

<Solution Include="$(BuildDirFullName)Source\BusinessBingo\BusinessBingo.sln">
	<Properties>	
		OutDir=$(OutDir);
      	Platform=Any CPU;
     	Configuration=Release;
      	DeployOnBuild=True;
      	DeployTarget=Package;
      	PackageLocation=$(OutDir)\MSDeploy\Package.zip;
      	_PackageTempDir=C:\Temp\Web
	</Properties>
</Solution>

  Deployment durchführen

Ruft man einfach so die "MSDeployMSBuild.Web.deploy.cmd” einfach so auf, dann wird die ReadMe angezeigt, denn es fehlen noch Daten: Wohin soll den überhaupt etwas deployt werden?

Als Beispiel wie ein Aufruf aussehen kann:

Package.deploy.cmd /Y /M:http://SERVER_NAME/MSDeployAgentService /U:USERDATEN /P:PASSWORT

Nun wird versucht das Package auf der eingestellten IIS Seite auf dem Server "SERVER_NAME” zu deployen. Über den Schalter /Y wird das Deployment durchgeführt. Nimmt man statt /Y das /T kann man einen testlauf machen - hierbei werden die Daten noch nicht übertragen.

Fazit

Mit wenigen Handgriffen kann man die Visual Studio Funktionalität aucch in ein Buildscript gießen. MSDeploy ist ein großes Thema. Ich will daher auch nicht ausschließen dass hier alles korrekt wiedergegeben ist - so jedenfalls hat es bei mir funktioniert :)

[ Download Democode ]


Written by Robert Muehsig

Software Developer - from Saxony, Germany - working on primedocs.io. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com | ExpensiveMeeting | EinKofferVollerReisen.de