For the past few months I’ve been working on a project I’m calling PSBuild. It’s an open source project on GitHub which makes the experience of calling MSBuild from PowerShell better. Getting started with PSBuild is really easy. You can install it in one line.

(new-object Net.WebClient).DownloadString("https://raw.github.com/ligershark/psbuild/master/src/GetPSBuild.ps1") | iex

You can find this info on the project home page as well.

 

When you install PSBuild one of the functions that you get is Invoke-MSBuild. When you call Invoke-MSBuild it will end up calling msbuild.exe. Some advantages of using Invoke-MSBuild are.

    • It uses the latest version of msbuild.exe installed by default

    • Mult-core builds by default

    • Writes a detailed and diagnostic log to %localappdata% by default. It’s easy to get to those logs as well

    • Good defaults for logging, including console logger

    • You can pass more than one file to build

    • Support for “Default Properties”

    Calling Invoke-MSBuild

    A most basic usage of Invoke-MSBuild.

    Invoke-MSBuild .\App.csproj
    

    This will build the project using the default targets. The call to msbuild.exe on my computer is below.

    C:\Program Files (x86)\MSBuild\12.0\bin\amd64\msbuild.exe 
        .\App.csproj 
        /m 
        /clp:v=m
        /flp1:v=d;logfile=C:\Users\Sayed\AppData\Local\PSBuild\logs\App.csproj-log\msbuild.detailed.log 
        /flp2:v=diag;logfile=C:\Users\Sayed\AppData\Local\PSBuild\logs\App.csproj-log\msbuild.diagnostic.log

    From the call to msbuild.exe you can see that the /m is passed as well as a couple file loggers in %localappdata%. We will get to the logs later. More on Invoke-MSBuild,

    To get a sense for how you can use Invoke-MSBuild take a look at the examples below.

    # VisualStudioVersion and Configuration MSBuild properties have easy to use parameters
    Invoke-MSBuild .\App.csproj -visualStudioVersion 12.0 -configuration Release
    
    # How to pass properties
    Invoke-MSBuild .\App.csproj -visualStudioVersion 12.0 -properties @{'DeployOnBuild'='true';'PublishProfile'='toazure';'Password'='mypwd-really'}
    
    # How to build a single target
    Invoke-MSBuild .\App.csproj -visualStudioVersion 12.0 -targets Clean
    
    # How to bulid multiple targets
    Invoke-MSBuild .\App.csproj -visualStudioVersion 12.0 -targets @('Clean','Build')
    

     

    Getting log files

    When you call Invoke-MSBuild on a project or solution the output will look something like the following.

    image

    Notice that line at the end. You can access your last log using the command.

    Open-PSBuildLog
    

    This will open the detailed log of the previous build in the program that’s associated with the .log extension. You can also use the Get-PSBuildLastLogs function to view the path for both log files written. If you want to view the folder where the log files are written to you can execute start (Get-PSBuildLogDirectory).

    Helper functions

    There are a couple of things that I’m constantly having to look up when I’m authoring MSBuild files; Reserved property names and escape characters. PSBuild has a helper function for each of these Get-MSBuildEscapeCharacters and Get-MSBuildReservedProperties. In the screenshot below you’ll see the result of executing each of these.

    image

     

    Default Properties

    The Invoke-MSBuild cmdlet has a property –defaultProperties. You can pass in a hashtable just like the –properties parameter. These properties are applied as environment variables before the call to msbuild.exe and then reverted afterwards. The effect here is that you can have a property value which will be used if no other value for that property is specified in MSBuild.

     

    There is so much more to PSBuild. This is just the tip of the iceberg. Keep an eye on the project page for more info. I’d love your help on this project. Please consider contributing to the project https://github.com/ligershark/psbuild.

     

    Thanks,
    Sayed Ibrahim Hashimi | http://msbuildbook.com/ | @SayedIHashimi


    Comment Section

    Comments are closed.


    Recently I encountered a customer asking if it’s possible to download a site using msdeploy.exe. This is pretty easy using msdeploy.exe. I’ll demonstrate this with Microsoft Azure Web Sites but you can use this with any hosting provider that supports Web Deploy (aka MSDeploy).

    To perform a sync with msdeploy.exe the structure of the command that we need to execute is as follows.

    msdeploy.exe –verb:sync –source: –dest:

    For the source property we will use the remote Azure Web Site, and for the dest property we will write to a folder on the local file system. You can get the Web Deploy publishing settings in the Azure Web Site by clicking on the Download the publish profile link in the Configure page.

    image

    This will download an XML file that has all the publish settings you’ll need. For example below is a publish settings file for my demo site.

    
      
        
      
      
        
      
    

    The publish settings file provided by Azure Web Sites has two profiles; an MSDeploy profile and an FTP profile. We can ignore the FTP profile and just use the MSDeploy one. The relevant settings from the profile that we will use are the following values.

    • publishUrl
    • msdeploySite
    • userName
    • usePWD

    We will use the contentPath MSDeploy provider to download the files. On the source parameter we will need to include the relevant details of the remote machine. The full command to execute is below. I’ll break it down a bit after the snippet.

    "C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe" 
        -verb:sync 
        -source:contentPath=sayeddemo2,
            ComputerName="https://waws-prod-bay-001.publish.azurewebsites.windows.net/msdeploy.axd?site=sayeddemo2",
            UserName=$sayeddemo2,Password=***removed***,AuthType='Basic'  
        -dest:contentPath=c:\temp\pubfromazure -disablerule:BackupRule
    

    The important parts of the command above are how the remote settings are passed to the source provider. On the dest side I’ve provided the location where the files should be downloaded to.

     

    Sayed Ibrahim Hashimi | http://msbuildbook.com/ | @SayedIHashimi


    Comment Section

    Comments are closed.


    If you haven’t heard I’m working on a project with Mads Kristensen called SideWaffle. SideWaffle is a Visual Studio Extension which contains many different Visual Studio Item and Project Templates. This is a community effort and all open source at https://github.com/ligershark/template-builder. You can create your own Item Templates and Project Templates and send a Pull Request for them to be included in the main repo. Check out the video below for more info on SideWaffle.

    SideWaffle intro video

    Item Templates are used by VS developers to create files using the Add New Item dialog. SideWaffle already contains a number of Item Templates such as; Angular Controller, robots.txt, SignalR Hub and Client, etc. For more info on how to create Item Templates with SideWaffle watch the 4 minute video below.

     

    Project Templates are the items that show up in the Add New Project dialog. They provide a starting point for developers creating new projects. SideWaffle already has a few project templates as well, such as a Google Chrome Extension. You can learn more about how to create Project Templates in this video.

     

    Now that we’ve gotten the intro out of the way, let’s explore how you can create your own SideWaffle.

    How to create your own SideWaffle

    The idea behind SideWaffle is that we will have a shared VS extension for popular VS Item and Project Templates. Instead of contributing to the main SideWaffle project you may be interested in creating your own distribution that does not have the standard templates. For example, I’ve heard from both the Orchard and Umbraco that they are interested in creating template packs for their communities. It wouldn’t make much sense to include those templates in the main SideWaffle project. Instead it would be best to create a separate distribution for each; OrchardWaffle and UmbracoWaffle.

    So how can you do this? It’s pretty easy actually. SideWaffle is built on top of a NuGet package, TemplateBuilder, which is also open source at https://github.com/ligershark/template-builder. All the core functionality of SideWaffle is contained in that NuGet package. To create your own SideWaffle follow these steps:

    • If you don’t have it already download and install the Visual Studio SDK, here is 2012 version
    • Create a new Visual Studio Package project
    • From the package manager console execute Install-Package TemplateBuilder –pre

    After you add the TemplateBuilder NuGet package a few things happen:

    1. The build process of the project is modified to support building Item and Project templates
    2. Your .vsixmanifest file is updated with two new Asset tags
    3. An ItemTemplates folder is created with a sample Item Template

    From here on you can build the project and after installing the generated .vsix you can have users easily create instances of your item or project templates.

    You can add additional Item Templates, as well as create Project Templates in your project. That’s pretty much all there is to getting started with your own Waffle pack.

    Let me know if you have any issues or comments.

    Happy Waffleing!

     

    Sayed Ibrahim Hashimi | http://msbuildbook.com | @SayedIHashimi


    Comment Section

    Comments are closed.


    When automating web publishing for Visual Studio projects in many cases your first step will be to create a publish profile for the project in VS. There are many cases in which you cannot, or would not like to do this. In this post I’ll show you how you can take an existing project and use an MSBuild file to drive the publish process. In that I’ll also show how you can extend the publish process without modifying either the project or any of its contents.

    Before we get too far into this, if you are not familiar with how to publish your VS web projects from the command line you can read our docs at ttp://www.asp.net/mvc/tutorials/deployment/visual-studio-web-deployment/command-line-deployment.

    When you publish a project from the command line using a publish profile you typically use the syntax below.

    msbuild .\MyProject.csproj /p:VisualStudioVersion=11.0 /p:DeployOnBuild=true /p:PublishProfile= 
    

    In this snippet we are passing in a handful of properties. VisualStudioVersion dictates which version of MSBuild targets are used during the build. See http://sedodream.com/2012/08/19/VisualStudioProjectCompatabilityAndVisualStudioVersion.aspx for more details on that. DeployOnBuild=true injects the publish process at the end of build. PublishProfile can either be the name of a publish profile which the project contains or it can be the full path to a publish profile. We will use PublishProfile with that second option, the full path.

    So we need to pass in the full path to a publish profile, which typically is a .pubxml file. A publish profile is just an MSBuild file. When you pass in PublishProfile and DeployOnBuild=true, then the publish profile is Imported into the build/publish process. It will supply the publish properties needed to perform the publish.

    Let’s see how that works. I have a sample project, MySite, which does not have any publish profiles created for it. I have created a publish profile, ToFileSys.pubxml, in another folder that will be used though. The contents of that file are below.

    ToFileSys.pubxml

    
      
        FileSystem
        False
        C:\temp\Publish\01
        False
      
    
    

    This publish profile will publish to a local folder. I just created this file in VS with a different project and then just copied it to the folder that I needed, and removed properties which are only used for the inside of VS experience. We can publish the MySite project using this profile with the command below.

    msbuild MySite.csproj 
                /p:VisualStudioVersion=11.0 
                /p:DeployOnBuild=true 
                /p:PublishProfile=C:\data\my-code\publish-samples\publish-injection\build\ToFileSys.pubxml 
    

    When you execute this the file specified in PublishProfile will be included into the build process.

    Taking it up a level

    steps

    Now let’s see how we can take this to the next level by having a single script that will be used to publish more than one project using this technique.

    In the sample files (which you can find links for at the end of the post). I have a solution with two web projects, MySite and MyOtherSite. Neither of these projects have any publish profiles created. I have created a script which will build/publish these projects which you can find at build\publish.proj in the samples. The contents of the file are shown below.

    publish.proj

    
    
        
      
        11.0
        Release
        
        $(MSBuildThisFileDirectory)..\BuildOutput\
        
        C:\temp\Publish\Output\    
      
      
      
        
          
            VisualStudioVersion=$(VisualStudioVersion);
            Configuration=$(Configuration);
            OutputPath=$(OutputRoot);
            WebPublishMethod=FileSystem;
            publishUrl=$(PublishFolder)MySite\;
            DeployOnBuild=true;
            DeployTarget=WebPublish;
            PublishProfile=$(MSBuildThisFileFullPath)
          
        
    
        
          
            VisualStudioVersion=$(VisualStudioVersion);
            Configuration=$(Configuration);
            OutputPath=$(OutputRoot);
            WebPublishMethod=FileSystem;
            publishUrl=$(PublishFolder)MyOtherSite\;
            DeployOnBuild=true;
            DeployTarget=WebPublish;
            PublishProfile=$(MSBuildThisFileFullPath)
          
        
      
      
      
        
      
    
      
    
      
        
      
      
    
    

    This file is pretty simple, it declares some properties which will be used for the build/publish process. Then it declares the projects to be built with an item list named ProjectsToBuild. When declaring ProjectsToBuild I use the AdditionalProperties metadata to specify MSBuild properties to be used during the build process for each project. Let’s take a closer look at those properties.

    
      VisualStudioVersion=$(VisualStudioVersion);
      Configuration=$(Configuration);
      OutputPath=$(OutputRoot);
      WebPublishMethod=FileSystem;
      publishUrl=$(PublishFolder)MySite\;
      DeployOnBuild=true;
      DeployTarget=WebPublish;
      PublishProfile=$(MSBuildThisFileFullPath)
    
    

    I’ll explain all the properties now. VisualStudioVersion, Configuration and OutputPath are all used for the build process. The other properties are related to publishing. If you want to publish from the file system those properties (WebPublishMethod, publishUrl, DeployOnBuild, and DeployTarget) must be set. The most important property there is PublishProfile.

    PublishProfile is set to $(MSBuildThisFileFullPath) which is the full path to publish.proj. This will instruct the build process of that project to import publish.proj when its build/publish process is started. It’s important to note that a “new instance” of the file will be imported. What that means is that the imported version of publish.proj won’t have access to any dynamic properties/items created in publish.proj.

    The reason why PublishProfile is specified there is so that we can extend the publish process from within publish.proj itself. publish.proj has a target, AfterWebPublish, which will be executed after each project is executed. Let’s see how this works.

    We can execute the publish process with the command below.

    msbuild .\build\publish.proj /p:VisualStudioVersion=11.0
    

    After executing this command the tail end of the result is shown in the image below.

    image

    In the image above you can see that the MyOtherSite project is being publish to the specified location in publish.proj and the AfterWebPublish target is executed as well.

     

    In this post we’ve seen how we can use an MSBuild file as a publish profile, and how to extend the publish process using that same file.

    You can download the samples at https://dl.dropboxusercontent.com/u/40134810/blog/publish-injection.zip. You can find the latest version in my publish-samples repository at publish-injection.

    Sayed Ibrahim Hashimi | http://msbuildbook.com | @SayedIHashimi


    Comment Section

    Comments are closed.


    A few weeks ago I blogged about a Visual Studio extension, Farticus, which I’m working on with Mads Kristensen. In that post I described how the default compression of a .vsix (the artifact that is created for a Visual Studio Package) is not as small as it could be. It’s better to get a fully compressed VSIX because when users install the component the download time can be significantly reduced. In that post I described how you could use the Zip task from the MSBuild Extension Pack to have a fully compressed .vsix file. I will now show you how I’ve simplified this.

    Icon for package VsixCompressVsixCompress

    Since my previous post I’ve created a NuGet package, VsixCompress which simplifies this greatly. If you have an existing Visual Studio package and want to have a fully compressed .vsix file then all you need to do is install the VsixCompress package.

    image

     

    After you install this package the following happens.

    1. NuGet package is downloaded and installed to the packages folder
    2. The project is edited to include an import for a new .targets file
    3. The build process is extended to compress the .vsix file automatically

    After installing this package once you build the generated .vsix is much smaller than before. In the default case where you select to create a new C# VS Package the created .vsix is 17kb. After adding VsixCompress the resulting .vsix is only 9kb. That’s almost half the size. That’s all you need to know for local development. If you have a build server setup then there are a couple of additional steps. Let’s go over those now.

    Build Server Support

    I have blogged before about issues of shipping build updates in NuGet. To briefly summarize, when leveraging NuGet Package Restore you have to be careful if any of those NuGet packages have build updates. When using Package Restore the NuGet packages which contain the imported .targets file(s) are restored after the build starts. What this means is that the .targets files will never be imported (or an old copy is imported in the case the file exists from a previous build). The only way to work around this is to restore the packages before the .sln/.csproj file themselves are built. You can read the full details at http://sedodream.com/2012/12/24/SlowCheetahBuildServerSupportUpdated.aspx. I have a NuGet package, PackageRestore, which can help here. Take a look at my previous post How to simplify shipping build updates in a NuGet package. Now that we’ve discussed all the details that you need let’s discuss what my plans are going forward with this.

    Plans going forward

    I’m hoping to add the following features over the course of the next few weeks.

    FYI VsixCompress is open source so you can take a look at the code, or better yet contribute at https://github.com/sayedihashimi/vsix-compress.

    Please let me know what you think of this!

    Sayed Ibrahim Hashimi | http://msbuildbook.com | @SayedIHashimi


    Comment Section

    Comments are closed.


    << Older Posts | Newer Posts >>