- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Monday, May 14, 2012

MSBuild how to execute a target after CoreCompile

I was on StackOverflow today and noticed a question along these lines “How to I create a target which is executed when CoreCompile is, and that is skipped when CoreCompile is skipped?” Below is my answer.

This is a tricky problem to solve for the general case, but it is pretty easy in your case because CoreCompile has special built in support for this scenario. Before I go into the details of how you can accomplish this with CoreCompile let me explain how it works in general.

Explanation of the general case

In MSBuild targets are skipped due to Incremental Building. Incremental Build is driven purely off of the Inputs and Outputs attributes on the Target itself. The inputs are a list of files that the target will "use" and the outputs are a list of files that are "generated" by the target. I'm using quotes because its a loose concept not a concrete one. To simplify it you can just treat inputs/outputs as lists of files. When the target is about to be executed MSBuild will take the inputs and compare the timestamps of them to the outputs. If all the outputs are newer then the inputs then the target will be skipped. (FYI If you want to know what happens when only some outputs are out-of-date read my blog athttp://sedodream.com/2010/09/23/MSBuildYouveHeardOfIncrementalBuildingButHaveYouHeardOfPartialBuilding.aspx).

In any case if you want a target to be skipped you have to craft your Inputs/Outputs correctly. In your case you want to skip your target whenever the CoreCompile is skipped, so at the surface it would seem that you could simply copy the Inputs/Outputs of CoreCompile but that doesn't work. It doesn't work because when CoreCompile is executed the files may be out-of-date but that target itself brings them up-to-date. Then when you target is executed since they are all up-to-date it will be skipped. You would have to copy the Inputs/Outputs and append an additional file to inputs/outputs which you target creates. This would ensure that your target wouldn't get skipped during that first pass.

Specific solution for CoreCompile

If you take a look at the project file you will see towards the bottom that the file Microsoft.Common.targets is Imported, this file will then import the language specific .targets file. For example it will Import either Microsoft.CSharp.targets or Microsoft.VisualBasic.targets (if you are using C# or VB). In those .targets files you will find CoreCompile defined. In the definition for CoreCompile you will find the following at the end.

<CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''"/>

This will call all the targets defined in the TargetsTriggeredByCompilation property. So if you want your target to be called whenever CoreCompile is executed you can extend that property. Here is how to do that.

<PropertyGroup>
  <TargetsTriggeredByCompilation>
    $(TargetsTriggeredByCompilation);
    MyCustomTarget
  </TargetsTriggeredByCompilation>
</PropertyGroup>

<Target Name="MyCustomTarget">
  <Message Text="MyCustomTarget called" Importance ="high"/>
</Target>

In this case I define the property TargetsTriggeredByCompilation and I append MyCustomTarget to it. It's very important that you include the $(TargetsTriggeredByCompilation); there, if you don't then you won't be appending but overwriting. So if anyone else used this technique you'd wipe out their target.

Below is an image showing where I build once and CoreCompile and MyCustomTarget are executed. Then the second build CoreCompile is skipped any MyCustomTarget is never called.

build-output

 

Sayed Ibrahim Hashimi @SayedIHashimi

msbuild | Visual Studio Monday, May 14, 2012 4:14:13 AM (GMT Daylight Time, UTC+01:00)  #     | 
Sunday, May 13, 2012

VS Web Publish: How to parameterize connection strings outside of web.config

If you have used the Visual Studio web publish in either VS 2010 or VS 11 to create Web Deploy packages then you probably know that we parameterize connection strings in web.config automatically. In case you are not familiar with Web Deploy parameters, they are a way to declare that you want to easily be able to update a value of something when publishing the package later on. Connection strings are good examples of something which typically needs to be updated during publish.

As I previously stated if you create a Web Deploy package in Visual Studio we will automatically create Web Deploy parameters for all your connection strings in web.config. Earlier today I saw a question on StackOverflow asking how to parameterize connection strings in non-web.config files (question actually asked something else, but I think this is what he’s really wanting). I created a sample showing how to do this. Below is what the connectionStrings element looks like in web.config.

<connectionStrings configSource="connectionStrings.config" />

And here is connectionStrings.config

<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
  <clear/>
  <add name="ApplicationServices"
           connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
           providerName="System.Data.SqlClient" />
  <add name="OtherConnectionString"
       connectionString="data source=.\SQLExpress;Integrated Security=SSPI;Initial Catalog=foo"
       providerName="System.Data.SqlClient"/>
</connectionStrings>

In order to parameterize these connection strings you will have to extend the Web Publish Pipeline. To do that create a file named {project-name}.wpp.targets in the root of the project in which you are working (for VS 11 projects you can place all this directly inside of the .pubxml files). This will be an MSBuild file which will get imported into the build/publish process. Below is the file which needs to be created.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <ItemGroup>
    <!-- Here we need to declare MSDeploy parameters for connection strings in connectionStrings.config -->
    <MsDeployDeclareParameters Include="ApplicationServices-ConnectionString" >
      <Kind>XmlFile</Kind>
      <Scope>connectionStrings.config$</Scope>
      <Match>/connectionStrings/add[@name='ApplicationServices']/@connectionString</Match>
      <Description>Connection string for ApplicationServices</Description>
      <DefaultValue>data source=(localhost);Initial Catalog=AppServices</DefaultValue>
      <Tags>SqlConnectionString</Tags>
    </MsDeployDeclareParameters>

    <MsDeployDeclareParameters Include="OtherConnectionString-ConnectionString" >
      <Kind>XmlFile</Kind>
      <Scope>connectionStrings.config$</Scope>
      <Match>/connectionStrings/add[@name='OtherConnectionString']/@connectionString</Match>
      <Description>Connection string for OtherConnectionString</Description>
      <DefaultValue>data source=(localhost);Initial Catalog=OtherDb</DefaultValue>
      <Tags>SqlConnectionString</Tags>
    </MsDeployDeclareParameters>
  </ItemGroup>

</Project>

Here you can see that I am creating values for MSDeployDeclareParameters. When you package/publish this item list is used to create the MSDeploy parameters. Below is an explanation of the metadata values each contain.

After you create this file you will need to close/re-open VS (it caches imported .targets files). Then you can create a web deploy package. When you do so these new parameters will be declared. In my case I then imported this in the IIS manager and here is the dialog which shows up for the parameters.

SNAGHTML94cce08

As you can see the Application Path parameter is shown there as well as my custom connection string values. When I update the values in the text box and opened connectionStrings.config on my web server they were the values I entered in the dialog box.

FYI I have uploaded this sample to my github account at ParameterizeConStringConfig.

Sayed Ibrahim Hashimi @SayedIHashimi

msbuild | MSBuild 4.0 | MSDeploy | Visual Studio | Web Deployment Tool | Web Publishing Pipeline Sunday, May 13, 2012 10:18:03 PM (GMT Daylight Time, UTC+01:00)  #     | 
Saturday, May 12, 2012

web.config transforms, they are invoked on package and publish not F5

\I receive a lot of questions regarding web.config transforms, which have existed in Visual Studio since 2010, and wanted to clear up the support that we have in this area. These transforms show up in the solution explorer underneath web.config as shown in the image below.

image

Since the names of these transforms include the build configuration many people expect that web.config will be transformed when they start debugging (F5) or run the app (CTRL+F5) in Visual Studio. But sadly this is not the case. These transforms are kicked in only when the web is packaged or published. I totally agree that this would be awesome, and I even blogged about how to enable it at http://sedodream.com/2010/10/21/ASPNETWebProjectsWebdebugconfigWebreleaseconfig.aspx. It may seem like it would be really easy for us to include this support in the box, but unfortunately that is not the case. The reason why we are not able to implement this feature at this time is because a lot of our tooling (and many partners) relies on web.config directly. For example when you drag and drop a database object onto a web form, it will generate a connection string into the web.config. There are a lot of features are like this. It is a significant investment for us to make a change of this level. We were not able to get this done for Visual Studio 11, but it is on our radar and we are looking to see what we can do in this area in the future.

Sayed Ibrahim Hashimi @SayedIHashimi

Visual Studio 2010 | web Saturday, May 12, 2012 3:29:15 AM (GMT Daylight Time, UTC+01:00)  #     | 
Sunday, May 06, 2012

Windows how to determine what is locking a given file

Have you ever tried to perform an operation on a file (i.e. delete) just to be faced with an error relating to the fact that an application is locking the file? This happens to me a lot, including just now. I was writing some code and tried to switch branches and was given the error below.

image

So I closed down Visual Studio as well as IIS Express as I figured those were the ones which had the lock on the file, and tried again (a few times actually Smile ) but continued to receive the error above. In order to determine which file had a handle open to that file I downloaded Handle from the sysinternals suite. (I actually already had the items downloaded inside of a Dropbox share which I use between multiple computers.) I then executed the command handle.exe nlog and the results are shown below. Note: I had to open a command prompt window to run handle.exe, for some reason it wasn’t working from a PowerShell prompt.

image

As you can see there was a rogue devenv.exe process holding on to the file. After killing the process I was able to proceed.

Sayed Ibrahim Hashimi @SayedIHashimi

diagnostic | windows Sunday, May 06, 2012 12:53:04 AM (GMT Daylight Time, UTC+01:00)  #     | 
Saturday, May 05, 2012

Git customizing colors for Windows including posh-git

I’ve been using Git for my open source projects recently and have been loving it. If you are like me and you like using the PowerShell prompt instead of the normal command prompt then you have to install posh-git. posh-git extends the PowerShell prompt to include information about the git repository and also makes remote operations simpler. After using git in this way I quickly noticed that the colors were not very readable. For example take a look at the screen shot below.

image

In the image above you can see that the text in dark red is difficult to read. This text comes from two different places. For the text relating to modified and untracked files, that is coming directly from git.exe and for the text after [master that is coming from posh-git. In order to make this easier to read we have to modify the color settings for both.

Modifying text color settings for git.exe

When using git.exe you can configure the color settings using git config. There are a bunch of color settings which you can control, which are all listed on the manpage for git config. In my case I want to update the color for modified files and untracked files, those can be configured with color.status.changed and color.status.untracked respectively. The color options that you have to pick from include:

In my case I wanted the text for those settings to be the same color as the master text in the image above. In order to set the color you can use the syntax:

git config <color-to-update> “foreground-color background-color attribute”

The attribute value can be any of these values; bold, dim, ul, blink and reverse.

In my case I executed the following command:

git config --global color.status.changed "cyan normal bold"
git config --global color.status.untracked "cyan normal bold"

Notice that I used the --global switch to indicate that I wanted the settings to be persisted in the global .gitconfig file instead of the one for the specific project that I was working on. So this got me to:

image

Almost there, now I need to modify the color for the summary provided by posh-git. A good resource for more info here is http://git-scm.com/book/ch7-1.html#Colors-in-Git.

Modifying text color for posh-git

posh-git stores all of it’s color settings in the $global:GitPromptSettings variable, you can see them declared in the GitPrompt.ps1 file. If you want to change the values for the colors you should not edit that file (that file might get updated later). Instead all you need to do is to override the value for the particular color after posh-git has been loaded. The best way to do this is to edit your PowerShell profile. This file is executed every time you open a PS prompt. You can find the location of this file by executing $profile in a PS prompt. In that file you should see a line initializing posh-git in my case it was:

. 'G:\Data\Development\OpenSource\posh-git\profile.example.ps1'

You should place your customizations after this statement. So in my case I wanted to change the summary text from dark red to yellow, so I added the following lines to my PS profile.

$global:GitPromptSettings.WorkingForegroundColor    = [ConsoleColor]::Yellow
$global:GitPromptSettings.UntrackedForegroundColor  = [ConsoleColor]::Yellow

I closed the PS window and opened a new one and now here is the result.

image

Now that’s better!

FYI if you are looking to install posh-git you can follow a simple walk through on Phil Haack’s blog at Better Git with PowerShell.

I’d like to thank Brad Wilson and Keith Dahlby for pointing me in the right direction regarding these settings.

 

Sayed Ibrahim Hashimi | @SayedIHashimi

My Github account

git | posh-git Saturday, May 05, 2012 10:48:23 PM (GMT Daylight Time, UTC+01:00)  #     | 
Friday, April 27, 2012

SlowCheetah VS 11 support and now on github

In case you are not familiar with SlowCheetah, it is a Visual Studio extension which allows you to transform app.config files in the same way that web.config files are. More info on the project page http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5.

I wanted to let everyone know that I have updated SlowCheetah to support Visual Studio 11 and I have also placed the project on github at https://github.com/sayedihashimi/slow-cheetah. Regarding the VS 11 support there is one known issue that we currently do not support the preview functionality on VS 11. This is an item which we will be fixing for the next release.

 

Thanks,
Sayed Ibrahim Hashimi @SayedIHashimi

Reminder: even though I work for Microsoft this is a personal project and not formally affiliated with Microsoft

msbuild | SlowCheetah | Visual Studio 11 | Visual Studio 2010 Friday, April 27, 2012 7:52:02 PM (GMT Daylight Time, UTC+01:00)  #     | 
Sunday, April 22, 2012

Visual Studio 11 Web Publish database section

If you have tried out the web publish feature in Visual Studio then you may have noticed the message seen in the image towards the end of the post in the database section.

We did not have time for VS 11 beta to light up these features, but if you want a sneak peak of the behavior then take a look at the channel 9 video I posted recently Dirt Simple Web and Database Deployment in Visual Studio 11. If you have any questions/feedback feel free to send me an email: sayedha [at] {Microsoft}dotCOM.

image

Thanks,

Sayed Ibrahim Hashimi @SayedIHashimi

Sunday, April 22, 2012 9:15:30 PM (GMT Daylight Time, UTC+01:00)  #     | 

Video about upcoming Visual Studio 11 web publish updates

Recently I recorded a video on Channel 9 with Brady Gaster Dirt Simple Web and Database Deployment in Visual Studio 11. In this video I show the work that we have done to enable Entity Framework Code First migrations during publish and I also cover the investments that we are making regarding incremental database schema publish when you are not using EF Code First. If you get a chance I’d love for you to watch the video and give feedback regarding the direction that we are taking with VS Web Publishing.

Thanks,
Sayed Ibrahim Hashimi @SayedIHashimi

Sunday, April 22, 2012 8:15:40 PM (GMT Daylight Time, UTC+01:00)  #     | 
Wednesday, March 14, 2012

Package web updated and video below

A couple months ago I blogged about a Package-Web which is a NuGet package that extends the web packaging process in Visual Studio to enable you to create a single package which can be published to multiple environments (it captures all of your web.config transforms and has the ability to transform on non-dev machines). Since that release I have updated the project and tonight I created a video which shows the features a bit you can check it out on Youtube. It’s embedded below.

You can install this via NuGet, the package name is PackageWeb.

image

Package-Web is an open source project and you can find it on my github account at https://github.com/sayedihashimi/package-web.

Thanks,
Sayed Ibrahim Hashimi @SayedIHashimi

msbuild | MSDeploy | Visual Studio | web | Web Deployment Tool | Web Development | Web Publishing Pipeline Wednesday, March 14, 2012 6:08:57 AM (GMT Standard Time, UTC+00:00)  #     | 
Saturday, February 18, 2012

How to create a Web Deploy package when publishing a ClickOnce project

The other day I saw a question on StackOverflow (link in resources below) asking How you can create a Web Deploy (AKA MSDeploy) package when publishing a ClickOnce project. The easiest way to do this is to use the Web Deploy command line utility, msdeploy.exe. With the command line you can easily create an MSDeploy package from a folder with a command like the following:

    %msdeploy% 
      -verb:sync 
      -source:contentPath="C:\Temp\_NET\WebPackageWithClickOnce\WebPackageWithClickOnce\bin\Debug\app.publish" 
      -dest:package="C:\Temp\_NET\WebPackageWithClickOnce\WebPackageWithClickOnce\bin\Debug\co-pkg.zip"

 

Here you can see that I’m using the sync verb, along with a contentPath provider (which points to a folder) as the source and the destination is using the package provider, this point to where I want the package to be stored.

Now that we understand how to create an MSDeploy package from a folder we need to extend the ClickOnce publish process to create a package. I’m not a ClickOnce expert, but the ClickOnce publish process is captured in MSBuild so after investigating for a bit I found the following relevant details.

Now that we know what target to extend as well as what property we can use to refer to the folder which has the content we can complete sample. We need to edit the project file. Below is the full contents which I have placed at the bottom of the project file (right above </Project>).

  <PropertyGroup>
    <WebDeployPackageName Condition=" '$(WebDeployPackageName)'=='' ">$(MSBuildProjectName).zip</WebDeployPackageName>
    <!--Unless specified otherwise, the tools will go to HKLM\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1 to get the installpath for msdeploy.exe.-->
    <MSDeployPath Condition="'$(MSDeployPath)'==''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\3@InstallPath)</MSDeployPath>
    <MSDeployPath Condition="'$(MSDeployPath)'==''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\2@InstallPath)</MSDeployPath>
    <MSDeployPath Condition="'$(MSDeployPath)'==''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1@InstallPath)</MSDeployPath>
    <MSDeployExe Condition=" '$(MSDeployExe)'=='' ">$(MSDeployPath)msdeploy.exe</MSDeployExe>
  </PropertyGroup>
  <Target Name="CreateWebDeployPackage" AfterTargets="Publish" DependsOnTargets="Publish">
    <!--
    %msdeploy% 
      -verb:sync 
      -source:contentPath="C:\Temp\_NET\WebPackageWithClickOnce\WebPackageWithClickOnce\bin\Debug\app.publish" 
      -dest:package="C:\Temp\_NET\WebPackageWithClickOnce\WebPackageWithClickOnce\bin\Debug\co-pkg.zip"
      -->
    <PropertyGroup>
      <Cmd>"$(MSDeployExe)" -verb:sync -source:contentPath="$(MSBuildProjectDirectory)\$(PublishDir)" -dest:package="$(OutDir)$(WebDeployPackageName)"</Cmd>
    </PropertyGroup>
    <Message Text="Creating web deploy package with command: $(Cmd)" />
    <Exec Command="$(Cmd)" />
  </Target>

Here I’ve created a couple properties as well as a new target, CreateWebDeployPackage. I have declared the property WebDeployPackageName which will be the name (excluding path) of the Web Deploy package which gets created. This defaults to the name of the project, but you can override it if you want. Next I define the property, MSDeployPath, which points to msdeploy.exe. It will pick the latest version.

The CreateWebDeployPackage target just constructs the full command line call which needs to be executed and invokes it using the Exec MSBuild task. There are a couple subtle details on the target itself though which are worth pointing out. The target has declared AfterTargets=”Publish” which means that it will be invoked after the Publish target. It also declares DependsOnTargets=”Publish”. Which means that whenever the target gets invoked that Publish will need to be executed before CreateWebDeployPackage.

Now that we have defined these updates when you publish your ClickOnce project (wither through Visual Studio or the command line/build servers) a Web Deploy package will be generated in the output folder which you can use to incrementally publish your ClickOnce app to your web server. You can find the latest version of this sample on my github repository.

Sayed Ibrahim Hashimi @SayedIHashimi

Resources

ClickOnce | IIS | Microsoft | msbuild | MSDeploy | web Saturday, February 18, 2012 6:47:30 PM (GMT Standard Time, UTC+00:00)  #     |