A couple of months ago I wrote a blog post MSBuild how to execute a target after CoreCompile in which I describe how you can execute a target if the CoreCompile target is executed, if CoreCompile is skipped then so will your other target. The draw back of the approach that I outlined in my previous post was that it required you to edit your .csproj/.vbproj/etc file itself. So if you had a scenario where you were building multiple projects then you would have to edit all of the project files. In this post I’ll describe how you can perform the same customization without having to edit the project file itself. Note this blog is in response to a question on StackOverflow Determine if MSBuild CoreCompile will run and call custom target.
Before we get to the solution for this particular case let me describe an extensibility hook that the C# and VB projects have. Most of the logic for building C# and VB projects is captured in the MSBuild targets file at C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets. If you take a look in that file you will notice at the top an import looking like the one below.
<Import Project="$(CustomBeforeMicrosoftCommonTargets)" Condition="'$(CustomBeforeMicrosoftCommonTargets)' != '' and Exists('$(CustomBeforeMicrosoftCommonTargets)')"/>
This statement will import a file (located at the value for CustomBeforeMicrosoftCommonTargets) if the property is not empty and the file exists. The default value for CustomBeforeMicrosoftCommonTargets is C:\Program Files (x86)\MSBuild\v4.0\Custom.Before.Microsoft.Common.targets. So if you drop an MSBuild file at that location it will modify the build process for every C#/VB project built on that machine. Alternatively if you do not want (or cannot due to ACLs) then you can drop the file somewhere else and then specify its location by overriding the CustomBeforeMicrosoftCommonTargets property. This is the approach that I will take here. I have created a sample solution which consists of two projects ProjA and ProjB. I also have a build script, build.proj, to automate the build for this. Below is the entire contents of build.proj.
In the Build target above I use the MSBuild task to build both ProjA and ProjB. As you can see I am passing the property CustomBeforeMicrosoftCommonTargets=$(FileToInject) which points to extend-corecompile.proj. By passing this property when ProjA, and ProjB, is built it will automatically import the extend-corecompile.proj file for the build process. You can see the contents of extend-corecompile.proj below.
If you have been following our blog and twitter accounts then you most likely have heard that some of the Web components of Visual Studio 2012 are now “Out of Band”. What that means is that we can update those components separately from Visual Studio itself. Because of this we will be posting updates on a regular basis. Today marks the first of these updates, and its targeting Visual Studio 2012 RC. In this post I will describe how to get the update and then what the update contains.
How to get the update
If you already have Visual Studio 2012 RC installed when you launch VS you will see a notification in the task tray like the image below.
Note: VS checks for updates once a day so if you don’t see this notification today its likely that the check has already been performed
After you click on the notification you will be brought to the Extension and Updates dialog. To get the web updates you should go to the Visual Studio Gallery tab and then click Update on the Web Tooling Extensions item.
After installing the update you will need to restart VS.
What is contained in the update
The goals that we had when creating this update mainly consisted of.
Fix key customer reported bugs which we didn’t have time to complete for the RC release
Test out the update mechanism publicly
Since the intent of this release was not to light up any new features you won’t find any new functionality, but you may discover that an issue you are running into has been fixed. Most of the bugs which we fixed were filed by customer on Microsoft Connect, though some came in through other channels. For the Connect bugs you will see a link to the bug details, for Connect bugs filed as private there will not be a link. Below you will find a list of the fixed bugs as well as a brief description of the bug.
Web publishing raises an exception due to <connectionStrings> content
If the root web.config contained elements under <connectionStrings> that did not have a name attribute an exception was raised.
Reported Bugs
Error while trying to publish ASP.NET Web API project (Connect private)
"Exception in Executing Publishing" when Build > Publish Selection (Connect private)
VS2012 RC consistently crashes when publishing WCF service to file share (Connect private)
Web publish doesn’t include all files if there is no project configuration matching the solution configuration
The drop down for Configuration on the publish dialog was mapped to Solution Configurations instead of Project Configurations. Because of this if a Solution Configuration was selected which did not have a corresponding Project Configuration the files would not be published. We have updated the dialog to show the correct value.
Reported Bugs
File export for web application not working properly (Connect private)
One-click Web Deployment using FTP does not work (Connect private)
Wrap up
We are really excited to be able to publish updates on a more regular basis and we hope that you will find that helpful as well. In case you guys were wondering if we listen to feedback/Connect bugs I hope that this post helps to show that we are listening to feedback and working to resolve bugs which get filed on Connect. Keep filing the bugs so that we can make our product even better. If you have already filed bugs on Connect then Thank You!
I have written a few posts recently describing out updated web publish experience. These new experience is available for both Visual Studio 2010 as well as Visual Studio 2012 RC. You can use the links below to download these updates in the Azure SDK download. Below are links for both versions.
Last week we rolled out some updates for our Visual Studio 2010 Web Publishing Experience. This post will give you an overview of the new features which we released. In the coming weeks there will be more posts getting into more details regarding individual features.
You can get these updates in the Windows Azure SDK for Visual Studio 2010. When you download that package there you will also get the latest tools for Azure development.
The new high level features include the following.
Updated Web Publish dialog
Support to import publish profiles (.publishSettings files)
Support to configure EF Code First migrations during publish
Support to create web packages in the publish dialog
Publish profiles now a part of the project and stored in version control by default
Publish profiles are now MSBuild files
Profile specific web.config transforms
Overview
When you right click on your Web Application Project (WAP) you will now see the new publish dialog.
On this tab you can import a .publishSettngs file, which many web hosts provide, and you can also manage your publish profiles. If you are hosting your site on Windows Azure Web Sites then you can download the publish profile on the dashboard of the site using the Download publish profile link. After you import this publish profile you will be brought to the Connection tab automatically.
On this tab you can see all the server configuration values which are needed for your client machine to connect to the server. Typically you don’t have to worry about the details of these values. Next you’ll go to the Settings tab.
On the Settings tab you can set the build configuration which should be used for the publish process, the default value here is Release. There is also a checkbox to enable you to delete any files on the server which do not exist in the project.
Below that checkbox you will see a section for databases. The sample project shown has an Entity Framework Code First model, named ContactsContext, and it uses Code First Migrations to manage the database schema. If you have any non-EF Code First connection strings in web.config then those databases will show up as well but the support for incrementally publishing the schema for those has not yet been finalized. We are currently working on that. You can visit my previous blog entry for more info on that.
If you imported a .publishSettings file with a connection string then that connection string would automatically be inserted in the textbox/dropdown for the connection string. If you did not then you can use the … button to create a connection string with the Connection String Builder dialog or you can simply type/paste in a connection string. For the EF Code First contexts you will see the Execute Code Frist Migrations checkbox. When you check this when your site is published the web.config will be transformed to enable the Code First migrations to be executed the first time that the context is accessed. Now you can move to the Preview tab.
When you first come to the Preview tab you will see a Start Preview button. Once you click this button you will see the file operations which would be performed once you publish. Since this site has never been published all the file operations are Add, as you can see in the image below. The other Action values include; Update and Delete.
Once you are ready to publish you can click the Publish button. You can monitor the progress of the publish process using the Output Window. If your publish profile had a value for the Destination URL then the site will automatically be opened in the default browser after the publish has successfully completed.
Publish Profiles
One of the other changes in the publish experience is that publish profiles are now stored as a part of your project. They are stored under the folder Properties\PublishProfiles (for VB projects its My Project\PublishProfiles) and the extension is .pubxml. You can see this in the image below.
These .pubxml files are MSBuild files and you can modify these files in order to customize the publish process. If you do not want the publish profile to be checked into version control you can simply exclude it from the project. The publish dialog will look at the files in the PublishProfiles folder so you will still be able to publish using that profile. You can also leverage these publish profiles to simply publishing from the command line. For example you can use the following syntax to publish from the command line.
msbuild.exe WebApplication2.csproj /p:DeployOnBuild=true;PublishProfile="pubdemo - Web Deploy";Password={INSERT-PASSWORD}
We have two sets of ASP.NET providers which currently exist; the ASP.NET SQL providers, and the ASP.NET Universal Providers. In VS 2010 the SQL providers were in only providers used for our project templates. In VS 2012 we have switched to using the Universal Providers. One of the drawbacks of the SQL providers is that it leverages DB objects of SQL server which are not available in SQL Azure.
In our updated web publish experience we have an Update Database checkbox which can be used to incrementally publish the database to the destination database. In this case if the source connection string is used by the ASP.NET SQL providers and you are publishing to SQL Azure then you will see the following message on the dialog.
The publish dialog is letting you know that the SQL providers are not compatible with SQL Azure and helps you convert to using the Universal Providers. After you install the Universal Providers the web.config entry will be commented out and new entries will be inserted for the Universal Providers. Your existing database will not be impacted, we’ll create a new connection string pointing to a new database. If you had any data in the SQL Providers database you will have to re-create those objects in the new database.
If you have any questions please feel free to directly reach out to me at sayedha(at){MicrosoftDOTCom}.
In Visual Studio 2010 we introduced a database publishing experience in the Package/Publish SQL (PP/SQL) properties page. This support relies on generating create scripts from the source database and then executing those scripts when you publish your web application. For more details regarding this feature take a look at Package/Publish SQL Tab, Project Properties. One of the negative aspects of the implementation that we have there is that the DB schema publishing is not incremental, it always executes create scripts. So in many cases you publish your app for the first time and things are great, but the next time you try to publish you receive errors because it tries to create DB objects which already exist.
In our improved publish dialog we have a new database publishing experience which is incremental, so you don’t run into the same issues when re-deploying your database. All of the configuration for this is within the publish dialog itself. If you have a project which already has DB publish settings on the Package/Publish SQL tab (under any build configuration/platform) then you will see the message shown in the image below.
The new incremental DB schema publish mechanism is not compatibly with the feature set on the PP/SQL tab. For each web publish profile you can either use the settings on the PP/SQL tab or you can opt-in to the new experience on the publish dialog. We implemented it this way in order to introduce the new feature set and to ensure that existing publish scenarios are not broken.
FYI there is a related post on why the Update database checkbox is disabled in the publish dialog which you may be interested in.
If you have any questions please feel free to directly reach out to me at sayedha(at){MicrosoftDOTCom}.
If you have tried out our new Web Publish experience in Visual Studio you may have noticed that the Update Database checkbox is disabled. See the image below.
The intended behavior of this checkbox is to enable you to incrementally publish your database schema from the source (the connection string in web.config) to the destination (whatever connection string is in the text box). The difference between an incremental publish and a typical publish is that for incremental publishes only changes are transferred from source to destination. With a full publish the first time that you publish your DB schema everything is created, and the next time that you try to publish you will receive an error because it tries to re-create existing DB objects.
The functionality of the Update database checkbox leverages an MSDeploy provider. We were hoping to complete that provider and give it to hosters in time for the release but we were unable to do so. We are working on completing the provider and partnering with hosters to install these in time for the launch of Visual Studio 2012 RTM.
In the mean time if you need to publish your DB schema you can use the Package/Publish SQL tab (caution: the DB publishing here is not incremental). If you are going to use the PP/Sql tab to publish to SQL Azure then there are some special consideraions that you will need to take. You can learn more about those by visiting http://msdn.microsoft.com/en-us/library/dd465343.aspx and searching for “Azure” on that page.
If you have any questions please feel free to directly reach out to me at sayedha(at){MicrosoftDOTCom}.
Wanted to let you know that I just released v2.3 of my Visual Studio extension SlowCheetah. If you are not familiar with SlowCheetah here is an intro. For client projects (i.e. non-web projects) it allows you to transform the app.config (or any XML file) on F5 (debug) or CTRL + F5, it also has a preview functionality which allows you to see the results of the transform quickly. For Web Projects it allows you to transform XML files during package/publish (and of course the preview functionality works in web projects too). The transform behavior is all in MSBuild targets/tasks so command line support is built in. It’s also easy to integrate SlowCheetah into CI servers.
Below are the updates that we have in v2.3.
Preview support in VS 11 In the previous version we added support for VS 11 but the preview functionality didn’t work because the preview tool we used in VS 2010 didn’t exist in VS 11. VS 11 now has a new diffing tool and in this version we now support invoking this new service.
ClickOnce related updates
ClickOnce support was added in a previous version but the support was limited to app.config. In this version when you publish an application using ClickOnce if you have transforms in any other XML file defined those transforms will be applied and published.
Setup projects updates Similar to ClickOnce the support for setup projects was limited to app.config only. In this version we now have support for all XML files not just app.config. There was also a bug in the previous version relating to setup projects. For setup projects if a file was being transformed from a linked file when you built the solution you would receive an error. We have fixed that bug.
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.
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.
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.
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.
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.
Kind = for this case it will always be Xmlfile, learn more
Scope = a regular expression to the file which needs to be modified
Match = an XPath expression to the attribute/element to be updated
Description = optional description (this will show up in the IIS manager if the pkg is imported)
DefaultValue = optional default value for the for the parameter
Tags = optional, for connection strings use SqlConnectionString
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.
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.