<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title>Sayed Ibrahim Hashimi - MSBuild, C#, Visual Studio, Training, and more</title>
  <link rel="alternate" type="text/html" href="http://sedodream.com/" />
  <link rel="self" href="http://sedodream.com/SyndicationService.asmx/GetAtom" />
  <icon>favicon.ico</icon>
  <updated>2012-02-04T15:14:30.7973697-05:00</updated>
  <author>
    <name>Sayed Ibrahim Hashimi</name>
  </author>
  <subtitle>MSBuild, C#, Visual Studio and more</subtitle>
  <id>http://sedodream.com/</id>
  <generator uri="http://dasblog.info/" version="2.3.9074.18820">DasBlog</generator>
  <entry>
    <title>SlowCheetah XML Updates for Setup projects, ClickOnce, F# and more</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2012/02/04/SlowCheetahXMLUpdatesForSetupProjectsClickOnceFAndMore.aspx" />
    <id>http://sedodream.com/PermaLink,guid,7b8fedd7-a264-4823-9719-b7030ac634ed.aspx</id>
    <published>2012-02-04T15:14:30.7973697-05:00</published>
    <updated>2012-02-04T15:14:30.7973697-05:00</updated>
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I blogged in December about SlowCheetah which is a Visual Studio add in which can
be used to transform app.config (<em>or any XML file for that matter</em>) in ways
similar to web.config. A few days back we released an update to this adding with a
few key items which are listed below.
</p>
        <ol>
          <li>
Support for ClickOnce</li>
          <li>
Support for Setup projects</li>
          <li>
Support for F# projects</li>
          <li>
Support for a custom diff viewer</li>
          <li>
Support for XP/Win server 2003</li>
          <li>
Better error handling, logging</li>
        </ol>
        <p>
I’ve created a set of samples for SlowCheetah which I’ll use to describe these new
features. Download links for the samples, as well as pointers to the latest versions
are at the bottom of this page.
</p>
        <h3>Support for ClickOnce
</h3>
        <p>
If you are building a windows client application (Win forms or WPF) then you can use
ClickOnce to publish this application. When you publish a project using ClickOnce
a setup.exe will be generated as well as an HTML page which can be served by a web
server to enable users to download it. When this setup.exe is generated all of the
files needed to run your application (including app.config) are placed inside of that
executable. When you have a project using SlowCheetah and you publish using a specific
configuration it will now publish the transformed app.config (as well as any other
transformed files).
</p>
        <p>
In order to demonstrate this I’ve created a sample WPF application which I will publish
with ClickOnce (<em>download link is at the bottom</em>). This project has an app.config
file as well as app.Debug.config and app.Release.config.
</p>
        <p>
Below is what the original <u><strong>app.config</strong></u>file looks like.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
  &lt;appSettings&gt;
    &lt;add key="appName" value="WPF Demo-Debug-default"/&gt;
    &lt;add key="url" value="http://localhost:8080/Default/"/&gt;
    &lt;add key="email" value="demo-default@contoso.com"/&gt;
  &lt;/appSettings&gt;
  
  &lt;connectionStrings&gt;
    &lt;clear /&gt;
    &lt;add name="RecordsDb" connectionString=".\SQLExpress;Initial Catalog=RecordsDb-Default;Integrated Security=true"/&gt;  
  &lt;/connectionStrings&gt;
  
&lt;/configuration&gt;</pre>
        <p>
And here is <strong><u>app.Debug.Config</u></strong></p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"&gt;
  
  &lt;appSettings&gt;
    &lt;add key="appName" value="WPF Demo-Debug" xdt:Transform="Replace" xdt:Locator="Match(key)"/&gt;
    &lt;add key="url" value="http://localhost:8080/" xdt:Transform="Replace" xdt:Locator="Match(key)"/&gt;
    &lt;add key="email" value="debug@contoso.com" xdt:Transform="Replace" xdt:Locator="Match(key)"/&gt;
  &lt;/appSettings&gt;

  &lt;connectionStrings&gt;
    &lt;add name="RecordsDb" connectionString=".\SQLExpress;Initial Catalog=RecordsDb;Integrated Security=true"
         xdt:Transform="Replace" xdt:Locator="Match(name)"/&gt;
  &lt;/connectionStrings&gt;
  
&lt;/configuration&gt;</pre>
        <p>
ddd
</p>
        <p>
As you can see I am transforming both the appSettings as well as the connection string.
The application itself is pretty simple, it has a single page which shows the following
values.
</p>
        <ul>
          <li>
App settings</li>
          <li>
Connection strings</li>
          <li>
Content of app.config</li>
        </ul>
        <p>
When I run this application in Debug mode I will get the following result.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb.png" width="999" height="705" />
          </a>
          <br />
        </p>
        <p>
In previous versions of SlowCheetah when you published your application with ClickOnce
the original version of app.config was getting published instead of the transformed
one. This was actually a bug in the .targets files for ClickOnce, but we have now
worked around it in the SlowCheetah .targets files. So let’s say that you have a ClickOnce
application and you need to publish different versions which have config changes then
you can now easily do that with SlowCheetah.
</p>
        <h3>Support for Setup projects
</h3>
        <p>
Visual Studio 2010 also has Setup projects, which can be used to generate an MSI.
When you create the MSI you can specify that it includes the outputs of a project
in the solution. We had a similar story here in which the original app.config was
being placed into the MSI instead of the transformed on in the output folder. We have
now fixed that and if you have a Setup project which reference a project with SlowCheetah
transforms then the transformed files will endup in the resulting MSI instead of the
original one.
</p>
        <h3>Support for F# projects
</h3>
        <p>
If you have F# project and tried SlowCheetah you probably noticed that the “Add Transforms”
menu item didn’t show up for those project types. They now do. 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_9.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_3.png" width="360" height="142" />
          </a>
        </p>
        <p>
After you invoke this command you will see a transform created for each configuration
defined for the project. In other project types these transform appear as child items,
but F# projects don’t support this in the same way as C#/VB projects so they will
not be nested. So they will show up as the following. 
<br /><a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_2.png" width="289" height="103" /></a></p>
        <p>
I created a very simple F# application to demonstrate the behavior, below is the code.
</p>
        <pre class="brush: csharp;">// A simple application to create the config and show results in the console
let settingOne = System.Configuration.ConfigurationManager.AppSettings.["settingOne"];
let settingTwo = System.Configuration.ConfigurationManager.AppSettings.["settingTwo"];
let settingthree = System.Configuration.ConfigurationManager.AppSettings.["settingThree"];


printfn "settingOne: %s" settingOne
printfn "settingTwo: %s" settingTwo
printfn "settingThree: %s" settingthree

printfn " "
printfn "Press any key to close"
System.Console.ReadKey(true)</pre>
        <p>
As you can see this app just reads a few config values from app.config and displays
them on the console. Here is the original <strong><u>app.config </u></strong>file.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
  &lt;appSettings&gt;
    &lt;add key="settingOne" value="one default value"/&gt;
    &lt;add key="settingTwo" value="two default value"/&gt;
    &lt;add key="settingThree" value="three default value"/&gt;
  &lt;/appSettings&gt;
&lt;/configuration&gt;</pre>
        <p>
Here is <strong><u>app.Debug.config</u></strong></p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"&gt;
  &lt;appSettings&gt;
    &lt;add key="settingOne" value="one Debug"
         xdt:Locator="Match(key)" xdt:Transform="Replace" /&gt;
    
    &lt;add key="settingTwo" value="two Debug"
         xdt:Locator="Match(key)" xdt:Transform="Replace" /&gt;
    
    &lt;add key="settingThree" value="three Debug"
         xdt:Locator="Match(key)" xdt:Transform="Replace" /&gt;
  &lt;/appSettings&gt;
&lt;/configuration&gt;</pre>
        <p>
There is a similar app.Release.config as well for this project.
</p>
        <p>
When I run this in <u><strong>Debug mode </strong></u>below is the result
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_11.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_4.png" width="672" height="128" />
          </a>
        </p>
        <p>
When I run this in <strong><u>Release mode</u></strong> below is the result.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_13.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_5.png" width="672" height="127" />
          </a>
        </p>
        <p>
As you can see F# project will now pickup up the transformed web.config file instead
of the original one when running.
</p>
        <h3>Support for a custom diff viewer
</h3>
        <p>
As you may know SlowCheetah has a Preview Transform functionality that allows you
to quickly see the difference between the source file and the transformed one. For
example in my Wpf.Transform project I have a app.config file and app.Debug.config
when I select one of the transforms I can see this menu item.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_15.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_6.png" width="432" height="197" />
          </a>
          <br />
When that menu item is invoked we open the Visual Studio diff viewer to show you the
difference between these two files. We have received a number of requests to support
different diff viewers and we have enabled this in the latest release.
</p>
        <p>
After installing SlowCheetah you can go to Tools-&gt;Options and then pick SlowCheetah
on the left hand side. You will see the following.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_17.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_7.png" width="648" height="379" />
          </a>
        </p>
        <p>
Here we have three settings which you can customize, they are outlined below.
</p>
        <table border="0" cellspacing="0" cellpadding="2" width="400">
          <tbody>
            <tr>
              <td valign="top" width="200">
                <p align="center">
                  <strong>
                    <u>Setting</u>
                  </strong>
                </p>
              </td>
              <td valign="top" width="200">
                <p align="center">
                  <strong>
                    <u>Description</u>
                  </strong>
                </p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="200">
Preview Tool Command Line</td>
              <td valign="top" width="200">
This is a string.Format string that should be used to construct the command to be
executed. Here {0} will be replaced with the full path to the original file and {1}
with the full path to the transformed file.</td>
            </tr>
            <tr>
              <td valign="top" width="200">
Preview Tool Executable Path</td>
              <td valign="top" width="200">
This is the full path to the .exe which should be invoked during preview. 
<br />
The default value for this is “C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\diffmerge.exe”
which is the diff viewer that VS uses by default.</td>
            </tr>
            <tr>
              <td valign="top" width="200">
Run Preview Tool</td>
              <td valign="top" width="200">
If this is set to False then a diff viewer will not be shown, instead the transformed
file will just be opened.</td>
            </tr>
          </tbody>
        </table>
        <p>
If you want to use KDiff with SlowCheetah then you need it to invoke the following
command:
</p>
        <p>
          <font face="Courier New">“C:\Program Files (x86)\KDiff3\kdiff3.exe” {Path-to-original-file}
{Path-to-transformed-file}</font>
        </p>
        <p>
So in this case I just have to update the value for Preview Tool Executable Path to
be C:\Program Files (x86)\KDiff3\kdiff3.exe. After that when I perform a transform
I will see something like.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_19.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/SlowCheetah-XML-Updates-for_9D84/image_thumb_8.png" width="1351" height="525" />
          </a>
        </p>
        <h3>Support for XP/Win server 2003
</h3>
        <p>
After publishing the original version of SlowCheetah users started complaining that
it didn’t work for either Windows XP or Windows Server 2003. This is because SlowCheetah
writes file under the %LocalAppData% folder. What I didn’t realize was that XP and
Win server 2003 don’t have this environment variable defined! Because of this I had
to update the logic of where to write the files if that environment variable didn’t
exist. Now everything works seamlessly. 
<br /></p>
        <h3>Better error handling, logging
</h3>
        <p>
We had some issues in previous builds and they were difficult to diagnose because
we didn’t have any logging support. We have now updated this and we should be able
to diagnose user issues much easier.
</p>
        <p>
 
</p>
        <p>
Below are a list of resources and pointers, I hope that you guys like these updates
and please do continue giving us feedback on this!
</p>
        <h3>Resources
</h3>
        <ul>
          <li>
            <a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5">SlowCheetah
download page</a>
          </li>
          <li>
            <a href="https://github.com/sayedihashimi/sayed-samples/raw/master/SlowCheetahSamples/Releases/SlowCheetahSamples-20120204.zip">Download
these samples in a .zip file</a>
          </li>
          <li>
            <a href="https://github.com/sayedihashimi/sayed-samples/tree/master/SlowCheetahSamples">My
github repo for the latest version of these samples</a>
          </li>
        </ul>
        <p>
Sayed Ibrahim Hashimi <a href="https://twitter.com/#!/sayedihashimi">@SayedIHashimi</a></p>
        <p>
          <em>Note: I work for Microsoft but this add in was not created nor is supported by
Microsoft.</em>
        </p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=7b8fedd7-a264-4823-9719-b7030ac634ed" />
      </div>
    </content>
  </entry>
  <entry>
    <title>How to take your web app offline during publishing</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2012/01/08/HowToTakeYourWebAppOfflineDuringPublishing.aspx" />
    <id>http://sedodream.com/PermaLink,guid,bc2ced18-9064-4f51-9167-05ec5595291c.aspx</id>
    <published>2012-01-08T15:44:39.3201165-05:00</published>
    <updated>2012-01-08T15:46:42.2315253-05:00</updated>
    <category term="IIS" label="IIS" scheme="http://sedodream.com/CategoryView,category,IIS.aspx" />
    <category term="Microsoft" label="Microsoft" scheme="http://sedodream.com/CategoryView,category,Microsoft.aspx" />
    <category term="MSBuild" label="MSBuild" scheme="http://sedodream.com/CategoryView,category,MSBuild.aspx" />
    <category term="MSDeploy" label="MSDeploy" scheme="http://sedodream.com/CategoryView,category,MSDeploy.aspx" />
    <category term="Visual Studio 2010" label="Visual Studio 2010" scheme="http://sedodream.com/CategoryView,category,VisualStudio2010.aspx" />
    <category term="web" label="web" scheme="http://sedodream.com/CategoryView,category,web.aspx" />
    <category term="Web Deployment Tool" label="Web Deployment Tool" scheme="http://sedodream.com/CategoryView,category,WebDeploymentTool.aspx" />
    <category term="Web Publishing Pipeline" label="Web Publishing Pipeline" scheme="http://sedodream.com/CategoryView,category,WebPublishingPipeline.aspx" />
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I received a customer email asking how they can take their web application/site offline
for the entire duration that a publish is happening from Visual Studio. An easy way
to take your site offline is to drop an app_offline.htm file in the sites root directory.
For more info on that you can read ScottGu’s post, link in below in resources section.
Unfortunately Web Deploy itself doesn’t support this <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-sadsmile" alt="Sad smile" src="http://sedodream.com/content/binary/Windows-Live-Writer/c7d918859eb1_A669/wlEmoticon-sadsmile_2.png" />.
If you want Web Deploy (aka MSDeploy) to natively support this feature please vote
on it at <a href="http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing">http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing</a>. 
</p>
        <p>
Since Web Deploy doesn’t support this it’s going to be a bit more difficult and it
requires us to perform the following steps:
</p>
        <ol>
          <li>
Publish app_offline.htm</li>
          <li>
Publish the app, and ensure that app_offline.htm is contained inside the payload being
published</li>
          <li>
Delete app_offline.htm</li>
        </ol>
        <p>
#1 will take the app offline before the publish process  begins. 
<br />
#2 will ensure that when we publish that app_offline.htm is not deleted (and therefore
keep the app offline) 
<br />
#3 will delete the app_offline.htm and bring the site back online
</p>
        <p>
Now that we know what needs to be done let’s look at the implementation. First for
the easy part. Create a file in your Web Application Project (WAP) named app_offline-template.htm.
This will be the file which will end up being the app_offline.htm file on your target
server. If you leave it blank your users will get a generic message stating that the
app is offline, but it would be better for you to place <strong>static HTML</strong> (<em>no
ASP.NET markup</em>) inside of that file letting users know that the site will come
back up and whatever other info you think is relevant to your users. When you add
this file you should change the Build Action to None in the Properties grid. This
will make sure that this file itself is not published/packaged. Since the file ends
in .htm it will by default be published. See the image below.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/c7d918859eb1_A669/image_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/c7d918859eb1_A669/image_thumb.png" width="288" height="380" />
          </a>
        </p>
        <p>
Now for the hard part. For Web Application Projects we have a hook into the publish/package
process which we refer to as “wpp.targets”. If you want to extend your publish/package
process you can create a file named {ProjectName}.wpp.targets in the same folder as
the project file itself. Here is the file which I created you can copy and paste the
content into your wpp.targets file. I will explain the significant parts but wanted
to post the entire file for your convince. <em>Note: you can grab my latest version
of this file from my github repo, the link is in the resource section below.</em></p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;
  &lt;Target Name="InitalizeAppOffline"&gt;
    &lt;!-- 
    This property needs to be declared inside of target because this is imported before
    the MSDeployPath property is defined as well as others --&gt;
    &lt;PropertyGroup&gt;
      &lt;MSDeployExe Condition=" '$(MSDeployExe)'=='' "&gt;$(MSDeployPath)msdeploy.exe&lt;/MSDeployExe&gt;
    &lt;/PropertyGroup&gt;    
  &lt;/Target&gt;

  &lt;PropertyGroup&gt;
    &lt;PublishAppOfflineToDest&gt;
      InitalizeAppOffline;
    &lt;/PublishAppOfflineToDest&gt;
  &lt;/PropertyGroup&gt;

  &lt;!--
    %msdeploy% 
      -verb:sync 
      -source:contentPath="C:\path\to\app_offline-template.htm" 
      -dest:contentPath="Default Web Site/AppOfflineDemo/app_offline.htm"
  --&gt;

  &lt;!--***********************************************************************
  Make sure app_offline-template.htm gets published as app_offline.htm
  ***************************************************************************--&gt;
  &lt;Target Name="PublishAppOfflineToDest" 
          BeforeTargets="MSDeployPublish" 
          DependsOnTargets="$(PublishAppOfflineToDest)"&gt;
    &lt;ItemGroup&gt;
      &lt;_AoPubAppOfflineSourceProviderSetting Include="contentPath"&gt;
        &lt;Path&gt;$(MSBuildProjectDirectory)\app_offline-template.htm&lt;/Path&gt;
        &lt;EncryptPassword&gt;$(DeployEncryptKey)&lt;/EncryptPassword&gt;
        &lt;WebServerAppHostConfigDirectory&gt;$(_MSDeploySourceWebServerAppHostConfigDirectory)&lt;/WebServerAppHostConfigDirectory&gt;
        &lt;WebServerManifest&gt;$(_MSDeploySourceWebServerManifest)&lt;/WebServerManifest&gt;
        &lt;WebServerDirectory&gt;$(_MSDeploySourceWebServerDirectory)&lt;/WebServerDirectory&gt;
      &lt;/_AoPubAppOfflineSourceProviderSetting&gt;

      &lt;_AoPubAppOfflineDestProviderSetting Include="contentPath"&gt;
        &lt;Path&gt;"$(DeployIisAppPath)/app_offline.htm"&lt;/Path&gt;
        &lt;ComputerName&gt;$(_PublishMsDeployServiceUrl)&lt;/ComputerName&gt;
        &lt;UserName&gt;$(UserName)&lt;/UserName&gt;
        &lt;Password&gt;$(Password)&lt;/Password&gt;
        &lt;EncryptPassword&gt;$(DeployEncryptKey)&lt;/EncryptPassword&gt;
        &lt;IncludeAcls&gt;False&lt;/IncludeAcls&gt;
        &lt;AuthType&gt;$(AuthType)&lt;/AuthType&gt;
        &lt;WebServerAppHostConfigDirectory&gt;$(_MSDeployDestinationWebServerAppHostConfigDirectory)&lt;/WebServerAppHostConfigDirectory&gt;
        &lt;WebServerManifest&gt;$(_MSDeployDestinationWebServerManifest)&lt;/WebServerManifest&gt;
        &lt;WebServerDirectory&gt;$(_MSDeployDestinationWebServerDirectory)&lt;/WebServerDirectory&gt;
      &lt;/_AoPubAppOfflineDestProviderSetting&gt;
    &lt;/ItemGroup&gt;

    &lt;MSdeploy
          MSDeployVersionsToTry="$(_MSDeployVersionsToTry)"
          Verb="sync"
          Source="@(_AoPubAppOfflineSourceProviderSetting)"
          Destination="@(_AoPubAppOfflineDestProviderSetting)"
          EnableRule="DoNotDeleteRule"
          AllowUntrusted="$(AllowUntrustedCertificate)"
          RetryAttempts="$(RetryAttemptsForDeployment)"
          SimpleSetParameterItems="@(_AoArchivePublishSetParam)"
          ExePath="$(MSDeployPath)" /&gt;
  &lt;/Target&gt;

  &lt;!--***********************************************************************
  Make sure app_offline-template.htm gets published as app_offline.htm
  ***************************************************************************--&gt;
  &lt;!-- We need to create a replace rule for app_offline-template.htm-&gt;app_offline.htm for when the app get's published --&gt;
  &lt;ItemGroup&gt;
    &lt;!-- Make sure not to include this file if a package is being created, so condition this on publishing --&gt;
    &lt;FilesForPackagingFromProject Include="app_offline-template.htm" Condition=" '$(DeployTarget)'=='MSDeployPublish' "&gt;
      &lt;DestinationRelativePath&gt;app_offline.htm&lt;/DestinationRelativePath&gt;
    &lt;/FilesForPackagingFromProject&gt;

    &lt;!-- This will prevent app_offline-template.htm from being published --&gt;
    &lt;MsDeploySkipRules Include="SkipAppOfflineTemplate"&gt;
      &lt;ObjectName&gt;filePath&lt;/ObjectName&gt;
      &lt;AbsolutePath&gt;app_offline-template.htm&lt;/AbsolutePath&gt;
    &lt;/MsDeploySkipRules&gt;
  &lt;/ItemGroup&gt;

  &lt;!--***********************************************************************
  When publish is completed we need to delete the app_offline.htm
  ***************************************************************************--&gt;
  &lt;Target Name="DeleteAppOffline" AfterTargets="MSDeployPublish"&gt;
    &lt;!--
    %msdeploy% 
      -verb:delete 
      -dest:contentPath="{IIS-Path}/app_offline.htm",computerName="...",username="...",password="..."
    --&gt;
    &lt;Message Text="************************************************************************" /&gt;
    &lt;Message Text="Calling MSDeploy to delete the app_offline.htm file" Importance="high" /&gt;
    &lt;Message Text="************************************************************************" /&gt;

    &lt;ItemGroup&gt;
      &lt;_AoDeleteAppOfflineDestProviderSetting Include="contentPath"&gt;
        &lt;Path&gt;$(DeployIisAppPath)/app_offline.htm&lt;/Path&gt;
        &lt;ComputerName&gt;$(_PublishMsDeployServiceUrl)&lt;/ComputerName&gt;
        &lt;UserName&gt;$(UserName)&lt;/UserName&gt;
        &lt;Password&gt;$(Password)&lt;/Password&gt;
        &lt;EncryptPassword&gt;$(DeployEncryptKey)&lt;/EncryptPassword&gt;
        &lt;AuthType&gt;$(AuthType)&lt;/AuthType&gt;
        &lt;WebServerAppHostConfigDirectory&gt;$(_MSDeployDestinationWebServerAppHostConfigDirectory)&lt;/WebServerAppHostConfigDirectory&gt;
        &lt;WebServerManifest&gt;$(_MSDeployDestinationWebServerManifest)&lt;/WebServerManifest&gt;
        &lt;WebServerDirectory&gt;$(_MSDeployDestinationWebServerDirectory)&lt;/WebServerDirectory&gt;
      &lt;/_AoDeleteAppOfflineDestProviderSetting&gt;
    &lt;/ItemGroup&gt;
    
    &lt;!-- 
    We cannot use the MSDeploy/VSMSDeploy tasks for delete so we have to call msdeploy.exe directly.
    When they support delete we can just pass in @(_AoDeleteAppOfflineDestProviderSetting) as the dest
    --&gt;
    &lt;PropertyGroup&gt;
      &lt;_Cmd&gt;"$(MSDeployExe)" -verb:delete -dest:contentPath="%(_AoDeleteAppOfflineDestProviderSetting.Path)"&lt;/_Cmd&gt;
      &lt;_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.ComputerName)' != '' "&gt;$(_Cmd),computerName="%(_AoDeleteAppOfflineDestProviderSetting.ComputerName)"&lt;/_Cmd&gt;
      &lt;_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.UserName)' != '' "&gt;$(_Cmd),username="%(_AoDeleteAppOfflineDestProviderSetting.UserName)"&lt;/_Cmd&gt;
      &lt;_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.Password)' != ''"&gt;$(_Cmd),password=$(Password)&lt;/_Cmd&gt;
      &lt;_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.AuthType)' != ''"&gt;$(_Cmd),authType="%(_AoDeleteAppOfflineDestProviderSetting.AuthType)"&lt;/_Cmd&gt;
    &lt;/PropertyGroup&gt;

    &lt;Exec Command="$(_Cmd)"/&gt;
  &lt;/Target&gt;  
&lt;/Project&gt;</pre>
        <h3>#1 Publish app_offline.htm
</h3>
        <p>
The implementation for #1 is contained inside the target PublishAppOfflineToDest.
The msdeploy.exe command that we need to get executed is.
</p>
        <p>
          <strong>msdeploy.exe 
<br />
    -source:contentPath='C:\Data\Personal\My Repo\sayed-samples\AppOfflineDemo01\AppOfflineDemo01\app_offline-template.htm' 
<br />
    -dest:contentPath='"Default Web Site/AppOfflineDemo/app_offline.htm"',UserName='sayedha',Password='password-here',ComputerName='computername-here',IncludeAcls='False',AuthType='NTLM'
-verb:sync -enableRule:DoNotDeleteRule</strong>
        </p>
        <p>
In order to do this I will leverage the MSDeploy task. Inside of the PublishAppOfflineToDest
target you can see how this is accomplished by creating an item for both the source
and destination.
</p>
        <h3>#2 Publish the app, and ensure that app_offline.htm is contained inside the payload
being published
</h3>
        <p>
This part is accomplished by the fragment
</p>
        <pre class="brush: xml;">  &lt;!--***********************************************************************
  Make sure app_offline-template.htm gets published as app_offline.htm
  ***************************************************************************--&gt;
  &lt;!-- We need to create a replace rule for app_offline-template.htm-&gt;app_offline.htm for when the app get's published --&gt;
  &lt;ItemGroup&gt;
    &lt;!-- Make sure not to include this file if a package is being created, so condition this on publishing --&gt;
    &lt;FilesForPackagingFromProject Include="app_offline-template.htm" Condition=" '$(DeployTarget)'=='MSDeployPublish' "&gt;
      &lt;DestinationRelativePath&gt;app_offline.htm&lt;/DestinationRelativePath&gt;
    &lt;/FilesForPackagingFromProject&gt;

    &lt;!-- This will prevent app_offline-template.htm from being published --&gt;
    &lt;MsDeploySkipRules Include="SkipAppOfflineTemplate"&gt;
      &lt;ObjectName&gt;filePath&lt;/ObjectName&gt;
      &lt;AbsolutePath&gt;app_offline-template.htm&lt;/AbsolutePath&gt;
    &lt;/MsDeploySkipRules&gt;
  &lt;/ItemGroup&gt;</pre>
        <p>
The item value for FilesForPackagingFromProject here will convert your app_offline-template.htm
to app_offline.htm in the folder from where the publish will be processed. Also there
is a condition on it so that it only happens during publish and not packaging. We
do not want app_offline-template.htm to be in the package (<em>but it’s not the end
of the world if it does either</em>).
</p>
        <p>
The element for MsDeploySkiprules will make sure that app_offline-template.htm itself
doesn’t get published. This may not be required but it shouldn’t hurt.
</p>
        <h3>#3 Delete app_offline.htm
</h3>
        <p>
Now that our app is published we need to delete the app_offline.htm file from the
dest web app. The msdeploy.exe command would be:
</p>
        <p>
%msdeploy% 
<br />
      -verb:delete 
<br />
      -dest:contentPath="{IIS-Path}/app_offline.htm",computerName="...",username="...",password="..." 
<br /></p>
        <p>
This is implemented inside of the DeleteAppOffline target. This target will automatically
get executed after the publish because I have included the attribute <strong>AfterTargets=”MSDeployPublish”</strong>.
In that target you can see that I am building up the msdeploy.exe command directly,
it looks like the MSDeploy task doesn’t support the delete verb. 
</p>
        <p>
If you do try this out please let me know if you run into any issues. I am thinking
to create a Nuget package from this so that you can just install that package. That
would take a bit of work so please let me know if you are interested in that.
</p>
        <h3>Resources
</h3>
        <ol>
          <li>
            <a href="https://github.com/sayedihashimi/sayed-samples/blob/master/AppOfflineDemo01/AppOfflineDemo01/AppOfflineDemo01.wpp.targets">The
latest version of my AppOffline wpp.targets file.</a>
          </li>
          <li>
            <a href="http://weblogs.asp.net/scottgu/archive/2006/04/09/442332.aspx">ScottGu’s
blog on app_offline.htm</a>
          </li>
        </ol>
        <p>
 
</p>
        <p>
Sayed Ibrahim Hashimi <a href="https://twitter.com/#!/sayedihashimi">@SayedIHashimi</a></p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=bc2ced18-9064-4f51-9167-05ec5595291c" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Updating XML files with MSBuild</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/12/29/UpdatingXMLFilesWithMSBuild.aspx" />
    <id>http://sedodream.com/PermaLink,guid,326e6702-b8d4-46c2-a5b4-c0f375493610.aspx</id>
    <published>2011-12-28T22:38:56.8939464-05:00</published>
    <updated>2011-12-28T22:42:28.4128106-05:00</updated>
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
Today I just saw a question posted on StackOverflow asking how to update an XML file
using MSBuild during a CI build executed from Team City.
</p>
        <p>
There is not correct single answer, there are several different ways that you can
update an XML file during a build. Most notably:
</p>
        <ol>
          <li>
Use SlowCheetah to transform the files for you 
</li>
          <li>
Use the TransformXml task directly 
</li>
          <li>
Use the built in (MSBuild 4.0) XmlPoke task 
</li>
          <li>
Use a third party task library 
</li>
        </ol>
        <h3>#1 Use SlowCheetah to transform the files for you
</h3>
        <p>
Before you start reading too far into this post let me go over option #3 first because
I think it’s the easiest approach and the most easily maintained. You can download
my <a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5">SlowCheetah
XML Transforms Visual Studio add in</a>. Once you do this for your projects you will
see a new menu command to transform a file on build (for web projects on package/publish).
If you want to get this working from a CI server, its pretty easy see my post at <a href="http://sedodream.com/2011/12/12/SlowCheetahXMLTransformsFromACIServer.aspx">http://sedodream.com/2011/12/12/SlowCheetahXMLTransformsFromACIServer.aspx</a>.
</p>
        <h4>#2 Use the TransformXml task directly
</h4>
        <p>
If you want a technique where you have a “main” XML file and you want to be able to
contain transformations to that file inside of a separate XML file then you can use
the TransformXml task directly. For more info see my previous blog post at <a href="http://sedodream.com/2010/11/18/XDTWebconfigTransformsInNonwebProjects.aspx">http://sedodream.com/2010/11/18/XDTWebconfigTransformsInNonwebProjects.aspx</a></p>
        <h3>#3 Use the built in XmlPoke task
</h3>
        <p>
Sometimes it doesn’t make sense to create an XML file with transformations for each
XML file. For example if you have an XML file and you want to modify a single value
but to create 10 different files the XML transformation approach doesn’t scale well.
In this case it might be easier to use the XmlPoke task. <em>Note this does require
MSBuild 4.0</em>.
</p>
        <p>
Below are the contents of sample.xml (<em>came from the SO question</em>).
</p>
        <pre class="brush: xml;">&lt;Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral"&gt;
  &lt;item&gt;
    &lt;key&gt;IsTestEnvironment&lt;/key&gt;
    &lt;value&gt;True&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
  &lt;item&gt;
    &lt;key&gt;HlrFtpPutDir&lt;/key&gt;
    &lt;value&gt;C:\DevPath1&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
  &lt;item&gt;
    &lt;key&gt;HlrFtpPutCopyDir&lt;/key&gt;
    &lt;value&gt;C:\DevPath2&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
&lt;/Provisioning.Lib.Processing.XmlConfig&gt;</pre>
        <p>
So in this case we want to update the values of the <strong>value</strong> element.
So the first thing that we need to do is to come up with the correct XPath for all
the elements which we want to update. In this case we can use the following XPath
expressions for each <strong>value</strong> element.
</p>
        <ul>
          <li>
/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</li>
          <li>
/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</li>
        </ul>
        <p>
I’m not going to go over what you need to do to figure out the correct XPath because
that’s not the purpose of this post. There are a bunch of XPath related resources
on the interwebs. In the resources section I have linked to the online XPath tester
which I always use.
</p>
        <p>
Now that we’ve got the required XPath expressions we need to construct our MSBuild
elements to get everything updated. Here is the overall technique:
</p>
        <ol>
          <li>
Place all info for all XML updates into an item</li>
          <li>
Use XmlPoke along with MSBuild batching to perform all the updates</li>
        </ol>
        <p>
For #2 if you are not that familiar with MSBuild batching then I would recommend <a href="http://www.amazon.com/gp/product/0735645248?ie=UTF8&amp;tag=sedodream-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0735645248">buying
my book</a> or you can take a look at the resources I have online relating to batching
(the link is below in resources section). Below you will find a simple MSBuild file
that I created, UpdateXm01.proj.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;Project ToolsVersion="4.0" DefaultTargets="UpdateXml" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;
  &lt;PropertyGroup&gt;
    &lt;SourceXmlFile&gt;$(MSBuildProjectDirectory)\sample.xml&lt;/SourceXmlFile&gt;
    &lt;DestXmlFiles&gt;$(MSBuildProjectDirectory)\result.xml&lt;/DestXmlFiles&gt;
  &lt;/PropertyGroup&gt;

  &lt;ItemGroup&gt;
    &lt;!-- Create an item which we can use to bundle all the transformations which are needed --&gt;
    &lt;XmlConfigUpdates Include="ConfigUpdates-SampleXml"&gt;
      &lt;XPath&gt;/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value&lt;/XPath&gt;
      &lt;NewValue&gt;H:\ReleasePath1&lt;/NewValue&gt;
    &lt;/XmlConfigUpdates&gt;
    
    &lt;XmlConfigUpdates Include="ConfigUpdates-SampleXml"&gt;
      &lt;XPath&gt;/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value&lt;/XPath&gt;
      &lt;NewValue&gt;H:\ReleasePath2&lt;/NewValue&gt;
    &lt;/XmlConfigUpdates&gt;
  &lt;/ItemGroup&gt;
  
  &lt;Target Name="UpdateXml"&gt;
    &lt;Message Text="Updating XML file at $(DestXmlFiles)" /&gt;
    &lt;Copy SourceFiles="$(SourceXmlFile)"
          DestinationFiles="$(DestXmlFiles)" /&gt;
    &lt;!-- Now let's execute all the XML transformations --&gt;
    &lt;XmlPoke XmlInputPath="$(DestXmlFiles)"
             Query="%(XmlConfigUpdates.XPath)"
             Value="%(XmlConfigUpdates.NewValue)"/&gt;
  &lt;/Target&gt;
&lt;/Project&gt;</pre>
        <p>
The parts to pay close attention to is the XmlConfigUpdates item and the contents
of the UpdateXml task itself. Regarding the XmlConfigUpdates, that name is arbitrary
you can use whatever name you want, you can see that the Include value (which typically
points to a file) is simply left at ConfigUpdates-SampleXml. The value for the Include
attribute is not used here. I would place a unique value for the Include attribute
for each file that you are updating. This just makes it easier for people to understand
what that group of values is for, and you can use it later to batch updates. The XmlConfigUpdates
item has these two metadata values:
</p>
        <ul>
          <li>
XPath</li>
          <ul>
            <li>
This contains the XPath required to select the element which is going to be updated</li>
          </ul>
          <li>
NewValue</li>
          <ul>
            <li>
This contains the new value for the element which is going to be updated</li>
          </ul>
        </ul>
        <p>
Inside of the UpdateXml target you can see that we are using the XmlPoke task and
passing the XPath as %(XmlConfigUpdate.XPath) and the value as %(XmlConfigUpdates.NewValue).
Since we are using the %(…) syntax on an item this start MSBuild batching. Batching
is where more than one operation is performed over a “batch” of values. In this case
there are two unique batches (1 for each value in XmlConfigUpdates) so the XmlPoke
task will be invoked two times. Batching can be confusing so make sure to read up
on it if you are not familiar.
</p>
        <p>
Now we can use msbuild.exe to start the process. The resulting XML file is:
</p>
        <pre class="brush: xml;">&lt;Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral"&gt;
  &lt;item&gt;
    &lt;key&gt;IsTestEnvironment&lt;/key&gt;
    &lt;value&gt;True&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
  &lt;item&gt;
    &lt;key&gt;HlrFtpPutDir&lt;/key&gt;
    &lt;value&gt;H:\ReleasePath1&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
  &lt;item&gt;
    &lt;key&gt;HlrFtpPutCopyDir&lt;/key&gt;
    &lt;value&gt;H:\ReleasePath2&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
&lt;/Provisioning.Lib.Processing.XmlConfig&gt;</pre>
        <p>
So now we can see how easy it was to use the XmlPoke task. Let’s now take a look at
how we can extend this example to manage updates to the same file for an additional
environment.
</p>
        <h4>How to manage updates to the same file for multiple different results
</h4>
        <p>
Since we’ve created an item which will keep all the needed XPath as well as the new
values we have a bit more flexibility in managing multiple environments. In this scenario
we have the same file that we want to write out, but we need to write out different
values based on the target environment. Doing this is pretty easy. Take a look at
the contents of UpdateXml02.proj below.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;Project ToolsVersion="4.0" DefaultTargets="UpdateXml" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;
  
  &lt;PropertyGroup&gt;
    &lt;SourceXmlFile&gt;$(MSBuildProjectDirectory)\sample.xml&lt;/SourceXmlFile&gt;
    &lt;DestXmlFiles&gt;$(MSBuildProjectDirectory)\result.xml&lt;/DestXmlFiles&gt;
  &lt;/PropertyGroup&gt;

  &lt;PropertyGroup&gt;
    &lt;!-- We can set a default value for TargetEnvName --&gt;
    &lt;TargetEnvName&gt;Env01&lt;/TargetEnvName&gt;
  &lt;/PropertyGroup&gt;
  
  &lt;ItemGroup Condition=" '$(TargetEnvName)' == 'Env01' "&gt;
    &lt;!-- Create an item which we can use to bundle all the transformations which are needed --&gt;
    &lt;XmlConfigUpdates Include="ConfigUpdates"&gt;
      &lt;XPath&gt;/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value&lt;/XPath&gt;
      &lt;NewValue&gt;H:\ReleasePath1&lt;/NewValue&gt;
    &lt;/XmlConfigUpdates&gt;
    
    &lt;XmlConfigUpdates Include="ConfigUpdates"&gt;
      &lt;XPath&gt;/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value&lt;/XPath&gt;
      &lt;NewValue&gt;H:\ReleasePath2&lt;/NewValue&gt;
    &lt;/XmlConfigUpdates&gt;
  &lt;/ItemGroup&gt;

  &lt;ItemGroup Condition=" '$(TargetEnvName)' == 'Env02' "&gt;
    &lt;!-- Create an item which we can use to bundle all the transformations which are needed --&gt;
    &lt;XmlConfigUpdates Include="ConfigUpdates"&gt;
      &lt;XPath&gt;/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value&lt;/XPath&gt;
      &lt;NewValue&gt;G:\SomeOtherPlace\ReleasePath1&lt;/NewValue&gt;
    &lt;/XmlConfigUpdates&gt;

    &lt;XmlConfigUpdates Include="ConfigUpdates"&gt;
      &lt;XPath&gt;/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value&lt;/XPath&gt;
      &lt;NewValue&gt;G:\SomeOtherPlace\ReleasePath2&lt;/NewValue&gt;
    &lt;/XmlConfigUpdates&gt;
  &lt;/ItemGroup&gt;
  
  &lt;Target Name="UpdateXml"&gt;
    &lt;Message Text="Updating XML file at $(DestXmlFiles)" /&gt;
    &lt;Copy SourceFiles="$(SourceXmlFile)"
          DestinationFiles="$(DestXmlFiles)" /&gt;
    &lt;!-- Now let's execute all the XML transformations --&gt;
    &lt;XmlPoke XmlInputPath="$(DestXmlFiles)"
             Query="%(XmlConfigUpdates.XPath)"
             Value="%(XmlConfigUpdates.NewValue)"/&gt;
  &lt;/Target&gt;
&lt;/Project&gt;</pre>
        <p>
The differences are pretty simple, I introduced a new property, TargetEnvName which
lets us know what the target environment is. (<em>note: I just made up that property
name, use whatever name you like</em>). Also you can see that there are two ItemGroup
elements containing different XmlConfigUpdate items. Each ItemGroup has a condition
based on the value of TargetEnvName so only one of the two ItemGroup values will be
used. Now we have a single MSBuild file that has the values for both environments.
When building just pass in the property TargetEnvName, for example <strong>msbuild
.\UpdateXml02.proj /p:TargetEnvName=Env02</strong>. When I executed this the resulting
file contains:
</p>
        <pre class="brush: xml;">&lt;Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral"&gt;
  &lt;item&gt;
    &lt;key&gt;IsTestEnvironment&lt;/key&gt;
    &lt;value&gt;True&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
  &lt;item&gt;
    &lt;key&gt;HlrFtpPutDir&lt;/key&gt;
    &lt;value&gt;G:\SomeOtherPlace\ReleasePath1&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
  &lt;item&gt;
    &lt;key&gt;HlrFtpPutCopyDir&lt;/key&gt;
    &lt;value&gt;G:\SomeOtherPlace\ReleasePath2&lt;/value&gt;
    &lt;encrypted&gt;False&lt;/encrypted&gt;
  &lt;/item&gt;
&lt;/Provisioning.Lib.Processing.XmlConfig&gt;</pre>
        <p>
You can see that the file has been updated with different paths in the <strong>value</strong> element.
</p>
        <h4>#4 Use a third party task library
</h4>
        <p>
If you are not using MSBuild 4 then you will need to use a third party task library
like the MSBuild Extension Pack (link in resources).
</p>
        <p>
Hope that helps.
</p>
        <h3>Resources
</h3>
        <ul>
          <li>
StackOverflow question: <a href="http://stackoverflow.com/questions/8658972/using-msbuild-i-want-to-update-a-config-file-with-values-from-teamcity">http://stackoverflow.com/questions/8658972/using-msbuild-i-want-to-update-a-config-file-with-values-from-teamcity</a></li>
          <li>
MSBuild batching: <a href="http://sedotech.com/Resources#Batching">http://sedotech.com/Resources#Batching</a></li>
          <li>
SlowCheetah – XML Transforms extension: <a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5">http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5</a></li>
          <li>
MSBuild Extension Pack (has a task to update XML files): <a href="http://msbuildextensionpack.codeplex.com/">http://msbuildextensionpack.codeplex.com/</a></li>
          <li>
Online XPath tester: <a href="http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm">http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm</a></li>
          <li>
          </li>
        </ul>
        <p>
Sayed Ibrahim Hashimi <a href="https://twitter.com/#!/sayedihashimi">@SayedIHashimi</a></p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=326e6702-b8d4-46c2-a5b4-c0f375493610" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Package once publish anywhere</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/12/24/PackageOncePublishAnywhere.aspx" />
    <id>http://sedodream.com/PermaLink,guid,a3b53276-c7c7-4150-855a-ccb03198052b.aspx</id>
    <published>2011-12-24T00:04:44.1540595-05:00</published>
    <updated>2011-12-24T00:04:44.1540595-05:00</updated>
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
When I discuss the web package features in Visual Studio one item that always comes
up is that people want to be able to create a single Web Deploy package and then publish
that to may different environments. One reason why they have a difficult time in doing
this is because when a web package is created the web.config transforms are executed
before the package is created and then only the transformed web.config file makes
it into the package. Also Web Deploy itself doesn’t have support for <a href="http://msdn.microsoft.com/en-us/library/dd465326.aspx" target="_blank">web.config
transforms</a>. Since I’ve heard this soo many times I decided to take matters into
my own hands and address this for existing Visual Studio 2010 scenarios. Here is what
I (note that this is <strong>not a Microsoft sponsored project</strong>, it’s a personal
project) have done.
</p>
        <p>
I have create a new Nuget package, <a href="http://nuget.org/packages/PackageWeb" target="_blank">PackageWeb</a>,
which you can use to address this. In this blog post I will focus on the user experience
and not discuss too many details about the implementation, but I will have later blog
posts to discuss how this was implemented. Since this is a Nuget package you have
to have Nuget installed. If you don’t go to <a href="http://nuget.org/" target="_blank">nuget.org</a> and
click the huge Install Nuget button. Here are the steps to get you started:
</p>
        <ol>
          <li>
Install the PackageWeb Nuget package</li>
          <li>
Create a web deployment package</li>
          <li>
Notice there is a Publish-Interactive.ps1 file in the package folder</li>
          <li>
Execute the Publish-Interactive.ps1 file from the package folder</li>
        </ol>
        <h3>#1 Install the PacakgeWeb Nuget package
</h3>
        <p>
To install the package just right-click on the web project in the Solution Explorer
and select <strong>Manage Nuget Packages</strong>. In the dialog that pops up just
search for <em>PackageWeb</em> and click on the install button.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/SNAGHTML6c282a.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="SNAGHTML6c282a" border="0" alt="SNAGHTML6c282a" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/SNAGHTML6c282a_thumb.png" width="644" height="431" />
          </a>
        </p>
        <p>
After you do this a few files will be added to your project and the package creation
process will be extended to include those files. Stay tuned to this blog for more
details on this part.
</p>
        <h3>#2 Create a web deployment package
</h3>
        <p>
For most who are interested they will already know how to do this, but if not don’t
worry its simple. Right-click on the project in solution explorer and pick <strong>Build
Deployment Package</strong>.
</p>
        <h3>#3 Notice there is a Publish-Interactive.ps1 file in the package folder
</h3>
        <p>
When the package is built (by default it is written to the <em>obj\{Configuration}\Package\</em> folder.
In that folder you will now see a Publish-Interactive.ps1 file.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_thumb.png" width="401" height="254" />
          </a>
        </p>
        <h3>#3 Execute the Publish-Interactive.ps1 file from the package folder
</h3>
        <p>
Now that we have everything setup let’s start publishing! First let’s take a look
at the project which I am publishing, here is a view of the relevant portions of the
project.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/SNAGHTML7bc0ff.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="SNAGHTML7bc0ff" border="0" alt="SNAGHTML7bc0ff" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/SNAGHTML7bc0ff_thumb.png" width="245" height="261" />
          </a>
        </p>
        <p>
In this image you can see that I have 4 web.config transforms (web.debug.config,web.release.config,web.Prod.config
and web.Test.config). I didn’t add any new build configurations to create the Test
and Prod files. I just create them and added them to the project. Now open a PowerShell
prompt and cd to the package folder. From there execute the command <strong>.\Publish-Interactive.ps1</strong>.
Once you start it you will see that a file copy progress indicator starts. I’m extracting
the package to a temp folder. The first thing that the script will do is to prompt
you for the web.config transform to be executed.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_4.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_thumb_1.png" width="845" height="92" />
          </a>
        </p>
        <p>
In the image above you can see that it detected all 4 web.config transforms. At this
point you just type in the name of the transform which you want to apply. I will pick
Release here for this demo. After that some magic will happen and you will start to
be prompted for some values. It will prompt you for Web Deploy endpoint info and for
any parameters which exist in the package.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_6.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_thumb_2.png" width="1349" height="257" />
          </a>
        </p>
        <p>
The first 5 prompts will always be the same, those are the Web Deploy endpoint values.
Notice the whatif here, if you want to simulate a publish then for whatif pass in
the value true. This will cause Web Deploy to go into a simulation mode, and it will
tell you everything that it would do, but no changes will be made.
</p>
        <p>
After the first 5 values you will be prompted for all the parameters which exist in
the package. These usually have default values (you can see default values printed
in <font style="background-color: #0000ff" color="#00ffff"><strong>cyan</strong></font>)
so if you want to go with the defaults just hit the enter key.
</p>
        <p>
After you enter all the parameter values you will see the message shown below.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_8.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_thumb_3.png" width="647" height="203" />
          </a>
        </p>
        <p>
You may not want to enter all these values everytime so to help with that when you
invoke Publish-Interactive.ps1 it will write a file, PublishConfiguration.ps1.readme,
which has all the parameter values (except password, you have to fill that one in).
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_12.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/Package-once-publish-anywhere_11CAA/image_thumb_5.png" width="1168" height="553" />
          </a>
        </p>
        <p>
If you want that file to be picked up, just remove the .readme from the extension
and the next time you invoke Publish-Interactive.ps1 it will pick up the PublishConfiguration.ps1
file and not annoy you!
</p>
        <p>
Currently I’m listing this project as <strong>Alpha quality</strong>, I will be able
to promote it to beta/RTM <strong>only with your help</strong>. Please download it
and try it out. Send the feedback to me either here or you can create an issue on
the <a href="https://github.com/sayedihashimi/package-web/issues" target="_blank">project’s
issue page</a>.
</p>
        <p>
          <strong>Note: As I stated previously this is not a Microsoft sponsored project, it
is a personal project.</strong>
        </p>
        <p>
Sayed Ibrahim Hashimi <a href="https://twitter.com/#!/sayedihashimi" target="_blank">@SayedIHashimi</a></p>
        <p>
          <em>Note: I work for Microsoft, but these are my own opinions</em>
        </p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=a3b53276-c7c7-4150-855a-ccb03198052b" />
      </div>
    </content>
  </entry>
  <entry>
    <title>SlowCheetah XML transforms from a CI server</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/12/12/SlowCheetahXMLTransformsFromACIServer.aspx" />
    <id>http://sedodream.com/PermaLink,guid,c0fa850a-7563-40de-a61a-c7501e28cd9f.aspx</id>
    <published>2011-12-12T00:02:42.7602471-05:00</published>
    <updated>2011-12-12T00:03:26.4250097-05:00</updated>
    <category term="MSBuild" label="MSBuild" scheme="http://sedodream.com/CategoryView,category,MSBuild.aspx" />
    <category term="SlowCheetah" label="SlowCheetah" scheme="http://sedodream.com/CategoryView,category,SlowCheetah.aspx" />
    <category term="Visual Studio" label="Visual Studio" scheme="http://sedodream.com/CategoryView,category,VisualStudio.aspx" />
    <category term="Visual Studio 2010" label="Visual Studio 2010" scheme="http://sedodream.com/CategoryView,category,VisualStudio2010.aspx" />
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
A few months ago I published a Visual Studio add-in, <a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5" target="_blank">SlowCheetah
– XML Transforms</a>, which enables you to transform any XML file during a build in
the same way that you can transform the web.config during publish/package for web
projects. Since then I’ve received numerous requests to demonstrate how the transforms
can be kicked in from a CI server. It’s actually pretty easy because all the logic
from a transform perspective is contained inside of MSBuild tasks/targets. The Visual
Studio add-in itself is only delivering the support for gestures/preview.
</p>
        <p>
Before I dive into how to enable this for a CI server let me explain how the plugin
works and then the CI integration will be come much clearer. When you load a project/solution
in Visual Studio for the first time after you installed SlowCheetah a set of files
will be written to %localappdata%\Microsoft\MSBuild\SlowCheetah\v1. Those file are:
</p>
        <p>
 
</p>
        <table border="0" cellspacing="0" cellpadding="2" width="774">
          <tbody>
            <tr>
              <td valign="top" width="258">
                <p align="center">
                  <strong>Name</strong>
                </p>
              </td>
              <td valign="top" width="514">
                <p align="center">
                  <strong>Description</strong>
                </p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="258">
Install-Manifest.xml</td>
              <td valign="top" width="514">
An XML file which describes the files that are installed. This is used by the plugin
itself, you should never have to do anything with this file.</td>
            </tr>
            <tr>
              <td valign="top" width="258">
SlowCheetah.Tasks.dll</td>
              <td valign="top" width="514">
The assembly which contains the MSBuild task which transforms XML files.</td>
            </tr>
            <tr>
              <td valign="top" width="258">
SlowCheetah.Transforms.targets</td>
              <td valign="top" width="514">
The MSBuild file which enables XML file transformation</td>
            </tr>
          </tbody>
        </table>
        <p>
 
</p>
        <p>
The add-in adds the following menu command to any XML file for supported project types.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/S_121C9/image_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/S_121C9/image_thumb.png" width="359" height="144" />
          </a>
        </p>
        <p>
When you click on this for the first time the add-in needs to make some changes to
your project file so you are prompted to accept that. After you do the following changes
are applied to your project file.
</p>
        <ol>
          <li>
A new MSBuild property SlowCheetahTargets is added to the project and it points to
the SlowCheetah.transforms.targets file in %localappdata%</li>
          <li>
An import for that file is added</li>
        </ol>
        <p>
More specifically the elements added to your project file are.
</p>
        <pre class="brush: xml;">&lt;PropertyGroup&gt;
  &lt;SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' "&gt;$(LOCALAPPDATA)\Microsoft\MSBuild\SlowCheetah\v1\SlowCheetah.Transforms.targets&lt;/SlowCheetahTargets&gt;
&lt;/PropertyGroup&gt;

&lt;Import Project="$(SlowCheetahTargets)" Condition="Exists('$(SlowCheetahTargets)')" /&gt;</pre>
        <p>
          <em>Note: If you look at your project file they will not be next to each other. The
property will be towards the top of the project file and the import towards the bottom.</em>
        </p>
        <p>
So now you might have an idea of why this won’t work on your CI server, the file SlowCheetah.Transforms.targets
will not exist in the %localappdata% folder. There is an easy to way to fix this which
doesn’t require any changes to your CI server. Check in the files and update your
import. Here is what I did:
</p>
        <ol>
          <li>
Create a folder named SlowCheetah in the same folder as my solution</li>
          <li>
Added SlowCheetah.Tasks.dll and SlowCheetah.Transforms.targets to that folder</li>
          <li>
Create a solution folder named SlowCheetah in the solution</li>
          <li>
Drag and drop the files from your SlowCheetah folder into the SolutionFolder</li>
          <li>
Updated my project file to point to these files</li>
        </ol>
        <p>
Now your solution should look roughly like the following image.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/S_121C9/image_4.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/S_121C9/image_thumb_1.png" width="285" height="116" />
          </a>
        </p>
        <p>
          <em>Note: Steps #3/#4 are not strictly required</em>
        </p>
        <p>
For #5 you’ll have to edit your project file, don’t worry its an easy modification.
Just follow these steps:
</p>
        <ol>
          <li>
Right click on the project and select unload</li>
          <li>
Right click on the unloaded project and select Edit</li>
          <li>
Update the value for the SlowCheetahTargets import</li>
        </ol>
        <p>
In my case the folder that I placed the files into is 1 directory above the project
itself. So the new value for the property is as follows.
</p>
        <pre class="brush: xml;">&lt;SlowCheetahTargets&gt;$(MSBuildProjectDirectory)\..\SlowCheetah\SlowCheetah.Transforms.targets&lt;/SlowCheetahTargets&gt;</pre>
        <p>
After that I checked in all the files, kicked off a build and viola the files are
transformed. Let me know if you need any more info. 
<br /></p>
        <p>
Sayed Ibrahim Hashimi – <a href="http://twitter.com/sayedihashimi" target="_blank">@SayedIHashimi</a></p>
        <p>
          <em>Note: I work for Microsoft, but these are my own opinions</em>
        </p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=c0fa850a-7563-40de-a61a-c7501e28cd9f" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Publish web + database incrementally</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/11/16/PublishWebDatabaseIncrementally.aspx" />
    <id>http://sedodream.com/PermaLink,guid,e86c9c20-0b76-4bc1-8261-173679eca5ab.aspx</id>
    <published>2011-11-16T17:32:56.3794471-05:00</published>
    <updated>2012-01-21T17:46:26.692894-05:00</updated>
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I get a lot of questions regarding how to publish your web plus your database incrementally.
The users of Database projects in Visual Studio 2010 are especially curious about
this and how we can integrate Web Deploy with VSDDcmd.exe. I’ve put together a sample
which shows how you can use Web Deploy to deploy your web content and VSDBcmd.exe
to incrementally publish your database, and the sample also shows how to do this from
Team Build.
</p>
        <p>
I am working on creating some more formal documentation for this, but I thought you
guys might find this useful before we are able to formalize it. At the end of the
post you will the link to download the sample. What you are going to find below is
an email which I sent to a tech writer who will be creating the formalized documentation.
</p>
        <p>
 
</p>
        <p>
What you are going to find here is a bit different from other references which you
may have seen but I think that this solution is going to work nicely for enterprise
customers. 
</p>
        <p>
Here were my guiding principles when creating this:
</p>
        <ul>
          <li>
· You should be able to easily publish from the dev machine in a similar way that
Team Build will 
<ul><li>
Publish process should not be drastically different when publishing locally versus
Team Build, if it is then it makes it easier for devs to make things work locally
but not in the team env. 
</li></ul></li>
          <li>
· Typical Team Build customers like to build the .sln file (<i>instead of hand crafting
.proj files which are responsible for building the individual projects</i>) 
</li>
          <li>
· We should be able to publish both Web + Web Service + DB in a single shot 
</li>
          <li>
· We should make it easy to define new environments 
</li>
          <li>
· You should be able to use the same outputs to publish to multiple environments if
you want to 
</li>
          <li>
· Admins should not have to give developers settings to target environments 
<ul><li>
i.e. connection strings for prod cannot be checked in via the developer. This rules
out using web.config transforms 
</li></ul></li>
        </ul>
        <p>
Let me break down the assets quickly:
</p>
        <table border="0" cellspacing="0" cellpadding="0">
          <tbody>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Asset name</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
                  <b>Description</b>
                </p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>ContactManager-WCF.sln</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
The solution file which will be built both locally and from Team Build
</p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Publish\Publish.proj</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
The MSBuild project file which contains the logic to publish
</p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Publish\EnvConfig\Env-Dev.proj</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
The MSBuild project file which contains the properties for the Dev environment.
</p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Publish\Publish-Dev.cmd</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
A script file which developers can double click to invoke a deploy. It just calls
out to MSBuild with the correct properties set.
</p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Publish\Reset-Local.cmd</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
You can ignore this, it’s just a script I was using to reset my target env so that
I could test publishing.
</p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Publish\Reset-Database.sql</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
Same as previous, you can ignore it just used for my own testing.
</p>
              </td>
            </tr>
            <tr>
              <td valign="top" width="313">
                <p>
                  <b>Pubish\Out</b>
                </p>
              </td>
              <td valign="top" width="310">
                <p>
The folder where the build output will be placed when building locally.
</p>
              </td>
            </tr>
          </tbody>
        </table>
        <p>
Here is what happens:
</p>
        <p>
Publish.proj has a set of targets which perform the deployment. If you want to publish
locally you will not use Visual Studio (<i>because if you did you wouldn’t be able
to publish all projects at the same time</i>), instead the developer will simply double
click the Publish\Publish-Dev.cmd file. When it is executed locally the Publish.proj
file will build the solution and then publish all the projects.
</p>
        <p>
At the very top of that file you will find the following Import statement
</p>
        <p>
&lt;Import Project="$(TargetEnvPropsFile)"/&gt;
</p>
        <p>
This import will use the property TargetEnvPropsFile to import the environment specific
properties. This gives the hook to easily define environment specific properties.
In my example case I have placed those properties in the file Publish\EnvConfig\Env-Dev.proj.
When publishing when I call msbuild.exe I specify the property /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj
which will import all the properties from that file. You can imagine that we can create
different files for different environments and we just specify a different property
value and the rest of the process stays the same.
</p>
        <p>
For environments which devs don’t have access to admins can create these property
files and just pass a different value for TargetEnvPropsFile.
</p>
        <p>
After the solution is built the Publish.proj file will perform the following:
</p>
        <ol>
          <li>
Publish the database using vsdbcmd.exe and pass in the .deploymanifest file which
was generated from the database project 
</li>
          <li>
Update the SetParameters.xml file to contain the env specific values for both web
projects 
</li>
          <li>
Execute the deploy.cmd file for both web projects to perform the publish 
</li>
        </ol>
        <p>
          <i>Note: I had to create a parameters.xml file for the ContactManager.Mvc project
in order to enable me to easily update the WCF endpoint value for the service.</i>
        </p>
        <h3>Team Build
</h3>
        <p>
In Team Build here is what we are going to do:
</p>
        <ul>
          <li>
Create a Team Build definition which will first build the .sln file and then the Publish.proj
file 
</li>
          <li>
Specify the properties which will cause the web packages to be created and also specify
the property for the target environment 
<ul><li>
See the image below for the Team Build setup 
</li></ul></li>
        </ul>
        <p>
In the Team Build situation there are these customizations that need to be made to
the Publish.proj file:
</p>
        <ul>
          <li>
Pick up the output location from what Team Build specifies 
</li>
          <li>
Ensure that Clean in not executed (taken care of by Team Build) 
</li>
          <li>
Ensure that the .sln is not built (taken care of by Team Build) 
</li>
        </ul>
        <p>
 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/Publish-web--database-incrementally_C110/01_2.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="01" border="0" alt="01" src="http://sedodream.com/content/binary/Windows-Live-Writer/Publish-web--database-incrementally_C110/01_thumb.png" width="1414" height="574" />
          </a>
        </p>
        <p>
          <i>Note: You can also specify the property /p:Whatif=true if you want to simulate
a publish (MSDeploy updates are spewed to the command line, and DB operations written
to a .sql file).</i>
        </p>
        <p>
          <strong>You can download the samples below, please send me any questions/concerns
with this approach.</strong>
        </p>
        <p>
          <a title="https://github.com/sayedihashimi/sayed-samples/raw/master/ContactManager-publish-example/ContactManager-publish-example-v01.zip" href="https://github.com/sayedihashimi/sayed-samples/raw/master/ContactManager-publish-example/ContactManager-publish-example-v01.zip">https://github.com/sayedihashimi/sayed-samples/raw/master/ContactManager-publish-example/ContactManager-publish-example-v01.zip</a>
        </p>
        <p>
You can find the latest sources for this at my github repository: <a href="https://github.com/sayedihashimi/sayed-samples/tree/master/ContactManager-publish-example">https://github.com/sayedihashimi/sayed-samples/tree/master/ContactManager-publish-example</a></p>
        <p>
Sayed Ibrahim Hashimi – <a href="http://sedodream.com/ct.ashx?id=7b98b9ee-5391-4ba5-9f64-bcbbe815035c&amp;url=http%3a%2f%2ftwitter.com%2f%23!%2fsayedihashimi">@SayedIHashimi</a></p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=e86c9c20-0b76-4bc1-8261-173679eca5ab" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Using a Web Deploy package to deploy to IIS on the dev box and to a third party host</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/11/08/UsingAWebDeployPackageToDeployToIISOnTheDevBoxAndToAThirdPartyHost.aspx" />
    <id>http://sedodream.com/PermaLink,guid,7b98b9ee-5391-4ba5-9f64-bcbbe815035c.aspx</id>
    <published>2011-11-08T00:11:43.2234797-05:00</published>
    <updated>2011-11-08T00:11:43.2234797-05:00</updated>
    <category term="IIS" label="IIS" scheme="http://sedodream.com/CategoryView,category,IIS.aspx" />
    <category term="MSBuild" label="MSBuild" scheme="http://sedodream.com/CategoryView,category,MSBuild.aspx" />
    <category term="MSDeploy" label="MSDeploy" scheme="http://sedodream.com/CategoryView,category,MSDeploy.aspx" />
    <category term="web" label="web" scheme="http://sedodream.com/CategoryView,category,web.aspx" />
    <category term="Web Deployment Tool" label="Web Deployment Tool" scheme="http://sedodream.com/CategoryView,category,WebDeploymentTool.aspx" />
    <category term="Web Development" label="Web Development" scheme="http://sedodream.com/CategoryView,category,WebDevelopment.aspx" />
    <category term="Web Publishing Pipeline" label="Web Publishing Pipeline" scheme="http://sedodream.com/CategoryView,category,WebPublishingPipeline.aspx" />
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>Note: I’d like to thank Tom Dykstra for helping me put this together</em>
        </p>
        <h3>Overview
</h3>
        <p>
In this tutorial you'll see how to use a <em>web deployment package</em> package to
deploy an application. A deployment package is a <em>.zip</em> file that includes
all of the content and metadata that's required to deploy an application. 
</p>
        <p>
Deployment packages are often used in enterprise environments. This is because a developer
or a continuous integration server can create the package without needing to know
things like passwords that are stored in <em>Web.config</em> files. Only the server
administrator who actually installs the package needs to know those passwords, and
that person can enter the details at installation time.
</p>
        <p>
In a smaller organization that doesn't have separate people for these roles, there's
less need for deployment packages. But you can also use deployment packages as a way
to back up and restore the state of an application. After you use a deployment package
to deploy, you can save the package,. Then if a subsequent deployment has a problem,
you can quickly and easily restore the application state to the earlier state by reinstalling
the earlier package. (This scenario is more complicated if database changes are involved,
however.)
</p>
        <p>
This tutorial shows how to use Visual Studio to create a package and IIS Manager to
install it. For information about how to create and install packages using the command
line, see <a href="http://msdn.microsoft.com/en-us/library/bb386521.aspx">ASP.NET
Deployment Content Map</a> on the MSDN web site.
</p>
        <p>
To keep things relatively simple, this example assumes you have already deployed the
application and its databases, and you only need to deploy a code update. You have
made the code update, and you are ready to deploy it first to your test environment
(IIS on your local computer) and then to your hosting provider. You have a Test build
configuration that you use for the test environment and you use the Release build
configuration for the production environment. In the example, the name of the Visual
Studio project is ContosoUniversity, and instructions for its initial deployment can
be found in a series of tutorials that will be published in December on the ASP.NET
web site. 
</p>
        <p>
The hosting provider shown, Cytanium.com, is one of many that are available, and its
use here does not constitute an endorsement or recommendation.
</p>
        <blockquote>
          <p>
            <strong>Note</strong> The following example uses separate packages for the test and
production environments, but you can also create a single deployment package that
can be used for both environments. This would require that you use Web Deploy parameters
instead of <em>Web.config</em> transformations for <em>Web.config</em> file changes
that depend on deployment destination. For information about how to use Web Deploy
parameters, see <a href="http://msdn.microsoft.com/en-us/library/ff398068.aspx">How
to: Use Parameters to Configure Deployment Settings When a Package is Installed</a>.
</p>
        </blockquote>
        <h3>Configuring the Deployment Package
</h3>
        <p>
In this section, you'll configure settings for the deployment package. Some of these
settings are the same ones that you set also for one-click publish, others are only
for deployment packages. 
</p>
        <p>
Open the <strong>Package/Publish Web</strong> tab of the <strong>Project Properties</strong> window
and select the <strong>Test</strong> build configuration.
</p>
        <p>
For this deployment you aren't making any database changes, so clear <strong>Include
all databases configured in Package/Publish SQL tab</strong>. Make sure <strong>Exclude
files from the App_Data folder</strong> is selected.
</p>
        <p>
Review the settings in the section labeled <strong>Web Deployment Package Settings</strong>:
</p>
        <ul>
          <li>
By default, deployment packages are created as <em>.zip</em> files. You don't need
to change this setting. 
</li>
          <li>
By default, deployment packages are created in the project's <em>obj\Test\Package</em> folder.
You don't need to change this setting. 
</li>
          <li>
The default IIS web application name is the name of the project with "_deploy"
appended to it. Remove that suffix. You want the application to be named just ContosoUniversity
in IIS on your computer. 
</li>
          <li>
For this tutorial you're not deploying IIS settings, so you don't need to enter a
password for that. 
</li>
        </ul>
        <p>
The <strong>Package/Publish Web</strong> tab now looks like this:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Package_Publish_Web_tab_Test_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Package_Publish_Web_tab_Test" border="0" alt="Package_Publish_Web_tab_Test" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Package_Publish_Web_tab_Test_thumb.png" width="632" height="767" />
          </a>
        </p>
        <p>
You also need to configure settings for deploying to the production environment. Select
the <strong>Release</strong> build configuration to do that.
</p>
        <p>
Change <strong>IIS Web site/application name to use on the destination server</strong> to
a string that will serve as a reminder of what you need to do later when this value
is displayed in the IIS Manager UI: "[clear this field]". The text box on
this page won't stay cleared even if you clear it, so entering this note to yourself
will remind you to clear this value later when you deploy. When you deploy to your
hosting provider, you will connect to a site, not to a server, and in this case you
want to deploy to the root of the site.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Package_Publish_Web_tab_Release_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Package_Publish_Web_tab_Release" border="0" alt="Package_Publish_Web_tab_Release" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Package_Publish_Web_tab_Release_thumb.png" width="634" height="769" />
          </a>
        </p>
        <h4>Creating a Deployment Package for the Test Environment
</h4>
        <p>
To create a deployment package, first make sure you've selected the right build configuration.
In the <strong>Solution Configurations</strong> drop-down box, select <strong>Test</strong>.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Solution_Configurations_dropdown_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Solution_Configurations_dropdown" border="0" alt="Solution_Configurations_dropdown" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Solution_Configurations_dropdown_thumb.png" width="559" height="95" />
          </a>
        </p>
        <p>
In <strong>Solution Explorer</strong>, right-click the project that you want to build
the package for and then select <strong>Build Deployment Package</strong>.
</p>
        <p>
The <strong>Output</strong> window reports successful a build and publish (package
creation) and tells you where the package was created.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Output_Window_package_creation_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Output_Window_package_creation" border="0" alt="Output_Window_package_creation" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Output_Window_package_creation_thumb.png" width="653" height="228" />
          </a>
        </p>
        <h4>Installing the Deployment Package in the Test Environment
</h4>
        <p>
The next step is to install the deployment package in IIS on your development computer. 
</p>
        <p>
Run <strong>IIS Manager</strong>. In the <strong>Connections</strong> pane of the <strong>IIS
Manager</strong> window, expand the local server node, expand the <strong>Sites</strong> node,
and select <strong>Default Web Site</strong>. Then in the <strong>Actions</strong> pane,
click <strong>Import Application</strong>. (If you don't see an <strong>Import Application</strong> link,
the most likely reason is that you have not installed Web Deploy. You can use the <a href="http://www.microsoft.com/web/downloads/platform.aspx">Web
Platform Installer</a> to install both IIS and Web Deploy.)
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Default_Web_Site_in_inetmgr_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Default_Web_Site_in_inetmgr" border="0" alt="Default_Web_Site_in_inetmgr" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Default_Web_Site_in_inetmgr_thumb.png" width="607" height="464" />
          </a>
        </p>
        <p>
In the <strong>Select the Package</strong> wizard step, navigate to the location of
the package you just created. By default, that's the <em>obj\Test\Package</em> folder
in your ContosoUniversity project folder. (A package created with the <strong>Release</strong> build
configuration would be in <em>obj\Release\Package</em>.)
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Package_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Select_the_Package_dialog_box" border="0" alt="Select_the_Package_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Package_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
Click <strong>Next</strong>. The <strong>Select the Contents of the Package</strong> step
is displayed.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Contents_of_the_Package_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Select_the_Contents_of_the_Package_dialog_box" border="0" alt="Select_the_Contents_of_the_Package_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Contents_of_the_Package_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
Click <strong>Next</strong>. 
</p>
        <p>
The step that allows you to enter parameter values is displayed. The <strong>Application
Path</strong> value defaults to "ContosoUniversity", because that's what
you entered on the <strong>Package/Publish Web</strong> tab of the <strong>Project
Properties</strong> window.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Enter_Application_Package_Information_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Enter_Application_Package_Information_dialog_box" border="0" alt="Enter_Application_Package_Information_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Enter_Application_Package_Information_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
Click <strong>Next</strong>. 
</p>
        <p>
The wizard asks if you want to delete files at the destination that aren't in the
source. 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Overwrite_Existing_Files_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Overwrite_Existing_Files_dialog_box" border="0" alt="Overwrite_Existing_Files_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Overwrite_Existing_Files_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
In this case you haven't deleted any files that you want to delete at the destination,
so the default (no deletions) is okay. Click <strong>Next</strong>. 
</p>
        <p>
          <strong>IIS Manager</strong> installs the package and reports its status.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Installation_Progress_and_Summary_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Installation_Progress_and_Summary_dialog_box" border="0" alt="Installation_Progress_and_Summary_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Installation_Progress_and_Summary_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
Click <strong>Finish</strong>. 
</p>
        <p>
Open a browser and run the application in test by going to the URL <code><a href="http://localhost/ContosoUniversity">http://localhost/ContosoUniversity</a></code>. 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Instructors_page_with_separate_name_fields_Test_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Instructors_page_with_separate_name_fields_Test" border="0" alt="Instructors_page_with_separate_name_fields_Test" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Instructors_page_with_separate_name_fields_Test_thumb.png" width="653" height="336" />
          </a>
        </p>
        <h4>Installing IIS Manager for Remote Administration
</h4>
        <p>
The process for deploying to production is similar except that you create the package
using the Release build configuration, and you install it in <strong>IIS Manager</strong> using
a remote connection to the hosting provider. But first you have to install the <strong>IIS
Manager</strong> feature that facilitates remote connections.
</p>
        <p>
Click the following link to use the Web Platform Installer for this task:
</p>
        <ul>
          <li>
            <a href="http://go.microsoft.com/?linkid=9655670">IIS Manager for Remote Administration
v1.1</a>
          </li>
        </ul>
        <h4>Connecting to Your Site at the Hosting Provider
</h4>
        <p>
After you install the <strong>IIS Manager for Remote Administration</strong>, run <strong>IIS
Manager</strong>. You see a new <strong>Start Page</strong> in <strong>IIS Manager</strong> that
has several <strong>Connect to ...</strong> links in a <strong>Connection tasks</strong> box.
(These options are also available from the <strong>File</strong> menu.)
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/IIS_Manager_Remote_Admin_Start_Page_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="IIS_Manager_Remote_Admin_Start_Page" border="0" alt="IIS_Manager_Remote_Admin_Start_Page" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/IIS_Manager_Remote_Admin_Start_Page_thumb.png" width="628" height="413" />
          </a>
        </p>
        <p>
In <strong>IIS Manager</strong>, click <strong>Connect to a site</strong>. In the <strong>Specify
Site Connection Details</strong> step, enter the <strong>Server name</strong> and <strong>Site
name</strong> values that are assigned to you by your provider, and then click <strong>Next</strong>.
For a hosting account at Cytanium.com, you get the server name from <strong>Service
URL</strong> in the Visual Studio 2010 section of the welcome email. The site name
is indicated by "Site/application" in the same section of the email. 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Specify_Site_Connection_Details_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Specify_Site_Connection_Details_dialog_box" border="0" alt="Specify_Site_Connection_Details_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Specify_Site_Connection_Details_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
In the <strong>Provide Credentials</strong> step, enter the user name and password
assigned by the provider, and then click <strong>Next</strong>:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Provide_Credentials_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Provide_Credentials_dialog_box" border="0" alt="Provide_Credentials_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Provide_Credentials_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
You might see a <strong>Server Certificate Alert</strong> dialog box. If you're sure
that you've entered the correct server and site name, click <strong>Connect</strong>.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Server_Certificate_Alert_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Server_Certificate_Alert_dialog_box" border="0" alt="Server_Certificate_Alert_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Server_Certificate_Alert_dialog_box_thumb.png" width="402" height="289" />
          </a>
        </p>
        <p>
In the <strong>Specify a Connection Name</strong> step, click <strong>Finish</strong>.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Specify_a_Connection_Name_dialog_box_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Specify_a_Connection_Name_dialog_box" border="0" alt="Specify_a_Connection_Name_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Specify_a_Connection_Name_dialog_box_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
After <strong>IIS Manager</strong> connects to the provider's server, a <strong>New
Feature Available</strong> dialog box might appear that lists administration features
available for download. Click <strong>Cancel</strong> — you've already installed everything
you need for this deployment.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/New_Feature_Available_dialog_box_Cytanium_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="New_Feature_Available_dialog_box_Cytanium" border="0" alt="New_Feature_Available_dialog_box_Cytanium" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/New_Feature_Available_dialog_box_Cytanium_thumb.png" width="610" height="419" />
          </a>
        </p>
        <p>
After the <strong>New Feature Available</strong> box closes, the <strong>IIS Manager</strong> window
appears. There's now a node in the <strong>Connections</strong> pane for the site
at the hosting provider.
</p>
        <h4>Creating a Package for the Production Site
</h4>
        <p>
The next step is to create a deployment package for the production environment. In
the Visual Studio <strong>Solution Configurations</strong> drop-down box, select the
Release build configuration.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Solution_Configurations_dropdown_Release_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Solution_Configurations_dropdown_Release" border="0" alt="Solution_Configurations_dropdown_Release" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Solution_Configurations_dropdown_Release_thumb.png" width="554" height="93" />
          </a>
        </p>
        <p>
In <strong>Solution Explorer</strong>, right-click the <strong>ContosoUniversity</strong> project
and then select <strong>Build Deployment Package</strong>.
</p>
        <p>
The <strong>Output</strong> window reports a successful build and publish (package
creation), and it tells you that the package is created in the <em>obj\Release\Package</em> folder
in your project folder.
</p>
        <h4>Installing the Package in the Production Environment
</h4>
        <p>
Now you can install the package in the production environment. In the <strong>IIS
Manager</strong><strong>Connections</strong> pane, select the new connection you
added earlier. Then click <strong>Import Application</strong>, which will walk you
through the same process you followed earlier when you deployed to the test environment. 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/IIS_Manager_with_provider_site_selected_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="IIS_Manager_with_provider_site_selected" border="0" alt="IIS_Manager_with_provider_site_selected" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/IIS_Manager_with_provider_site_selected_thumb.png" width="646" height="521" />
          </a>
        </p>
        <p>
In the <strong>Select the Package</strong> step, select the package that you just
created:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Package_dialog_box_Prod_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Select_the_Package_dialog_box_Prod" border="0" alt="Select_the_Package_dialog_box_Prod" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Package_dialog_box_Prod_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
In the <strong>Select the Contents of the Package</strong> step, leave all the check
boxes selected and click <strong>Next</strong>:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Contents_of_the_Package_dialog_box_Prod_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Select_the_Contents_of_the_Package_dialog_box_Prod" border="0" alt="Select_the_Contents_of_the_Package_dialog_box_Prod" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Select_the_Contents_of_the_Package_dialog_box_Prod_thumb.png" width="650" height="500" />
          </a>
        </p>
        <p>
In the <strong>Enter Application Package Information</strong> step, clear the <strong>Application
Path</strong> and click <strong>Next</strong>:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Enter_Application_Package_Information_dialog_box_Prod_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Enter_Application_Package_Information_dialog_box_Prod" border="0" alt="Enter_Application_Package_Information_dialog_box_Prod" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Enter_Application_Package_Information_dialog_box_Prod_thumb.png" width="641" height="491" />
          </a>
        </p>
        <p>
The wizard asks if you want to delete files at the destination that aren't in the
source. 
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Overwrite_Existing_Files_dialog_box_4.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Overwrite_Existing_Files_dialog_box" border="0" alt="Overwrite_Existing_Files_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Overwrite_Existing_Files_dialog_box_thumb_1.png" width="650" height="500" />
          </a>
        </p>
        <p>
You don't need to have anything deleted, so just click <strong>Next</strong>. 
</p>
        <p>
When you get the warning about installing to the root folder, click <strong>OK</strong>:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Installation_in_root_folder_warning_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Installation_in_root_folder_warning" border="0" alt="Installation_in_root_folder_warning" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Installation_in_root_folder_warning_thumb.png" width="530" height="219" />
          </a>
        </p>
        <p>
Package installation begins. When it's done, the <strong>Installation Progress and
Summary</strong> dialog box is shown:
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Installation_Progress_and_Summary_dialog_box_4.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Installation_Progress_and_Summary_dialog_box" border="0" alt="Installation_Progress_and_Summary_dialog_box" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Installation_Progress_and_Summary_dialog_box_thumb_1.png" width="650" height="500" />
          </a>
        </p>
        <p>
Click <strong>Finish</strong>. Your application has been deployed to the hosting provider's
server, and you can test by browsing to your public site's URL.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Instructors_page_with_separate_name_fields_Prod_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Instructors_page_with_separate_name_fields_Prod" border="0" alt="Instructors_page_with_separate_name_fields_Prod" src="http://sedodream.com/content/binary/Windows-Live-Writer/b763f270a538_125B5/Instructors_page_with_separate_name_fields_Prod_thumb.png" width="616" height="294" />
          </a>
        </p>
        <p>
You've now seen how to deploy an application update by manually creating and installing
a deployment package. For information about how to create and install packages from
the command line in order to be able to integrate them into a continuous integration
process, see the <a href="http://msdn.microsoft.com/en-us/library/bb386521.aspx">ASP.NET
Deployment Content Map</a> on the MSDN web site.
</p>
        <p>
Sayed Ibrahim Hashimi – <a href="http://twitter.com/#!/sayedihashimi" target="_blank">@SayedIHashimi</a></p>
        <p>
ddd
</p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=7b98b9ee-5391-4ba5-9f64-bcbbe815035c" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Setting Folder Permissions on Web Publish</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/11/08/SettingFolderPermissionsOnWebPublish.aspx" />
    <id>http://sedodream.com/PermaLink,guid,3d4f59f9-55bf-4b7b-809f-da6ef4774f4c.aspx</id>
    <published>2011-11-07T23:49:54.4092691-05:00</published>
    <updated>2011-11-07T23:49:54.4092691-05:00</updated>
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>Note: I’d like to thank Tom Dykstra for helping me put this together</em>
        </p>
        <p>
As part of the deployment process you might need to set permissions on one or more
folders in the destination web application. For example, if your application allows
users to upload files, it needs write access to a folder in order to store the uploaded
files. By default, the<em>web publishing pipeline</em> (the automated deployment process)
automatically sets write permission on the <em>App_Data</em> folder in order to enable
database updates in case you store databases in that folder, and you can use the same
method to make the deployment process automatically set permissions on any folder
you choose.
</p>
        <h3>The &lt;projectname&gt;.wpp.targets File
</h3>
        <p>
The web publishing pipeline is controlled by MSBuild <em>.targets</em> files that
are installed with Visual Studio. Rather than editing the Visual Studio <em>.targets</em> files,
you can create a project-specific <em>.targets</em> file that Visual Studio will use
to modify the deployment process for a specific project. To do that, you create an
XML file in the project folder and name it <em>&lt; projectname&gt;.wpp.targets</em>.
The following example shows XML markup that causes the web publishing pipeline to
set write permissions for a folder named <em>Elmah</em> located in the root folder
of the application. The sample is designed to work for both deployment methods: publish
or web deployment package.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;

  &lt;Target Name="SetupCustomAcls" AfterTargets="AddIisSettingAndFileContentsToSourceManifest"&gt;   
    &lt;ItemGroup&gt;
      &lt;MsDeploySourceManifest Include="setAcl"&gt;
        &lt;Path&gt;$(_MSDeployDirPath_FullPath)\Elmah&lt;/Path&gt;
        &lt;setAclAccess&gt;Read,Write&lt;/setAclAccess&gt;
        &lt;setAclResourceType&gt;Directory&lt;/setAclResourceType&gt;
        &lt;AdditionalProviderSettings&gt;setAclResourceType;setAclAccess&lt;/AdditionalProviderSettings&gt;
      &lt;/MsDeploySourceManifest&gt;
    &lt;/ItemGroup&gt;
  &lt;/Target&gt;

  &lt;Target Name="DeclareCustomParameters" AfterTargets="AddIisAndContentDeclareParametersItems"&gt;
    &lt;ItemGroup&gt;
      &lt;MsDeployDeclareParameters Include="ElmahSetAclParam"&gt;
        &lt;Kind&gt;ProviderPath&lt;/Kind&gt;
        &lt;Scope&gt;setAcl&lt;/Scope&gt;
        &lt;Match&gt;^$(_EscapeRegEx_MSDeployDirPath)\\Elmah$&lt;/Match&gt;
        &lt;Description&gt;Add write permission to the Elmah folder.&lt;/Description&gt;
        &lt;DefaultValue&gt;{$(_MsDeployParameterNameForContentPath)}/Elmah&lt;/DefaultValue&gt;
        &lt;Value&gt;$(_DestinationContentPath)/Elmah&lt;/Value&gt;
        &lt;Tags&gt;Hidden&lt;/Tags&gt;
        &lt;Priority&gt;$(VsSetAclPriority)&lt;/Priority&gt;
        &lt;ExcludeFromSetParameter&gt;True&lt;/ExcludeFromSetParameter&gt;
      &lt;/MsDeployDeclareParameters&gt;
    &lt;/ItemGroup&gt;
  &lt;/Target&gt;
  
&lt;/Project&gt;</pre>
        <p>
The first <code>Target</code> element ("SetupCustomAcls") causes a <code>setAcl</code> action
to be added to the deployment package's <em>source manifest</em> when the package
is created. The source manifest is a file that specifies what to include in the deployment
package. The path to the folder is specified using an MSBuild variable (<code>_MSDeployDirPath_FullPath</code>)
that specifies the path to the project root folder:
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;sitemanifest&gt;  &lt;IisApp path="C:\ContosoUniversity\ContosoUniversity\obj\Release\Package\PackageTmp" managedRuntimeVersion="v4.0" /&gt;
  &lt;setAcl path="C:\ContosoUniversity\ContosoUniversity\obj\Release\Package\PackageTmp" setAclResourceType="Directory" /&gt;
  &lt;setAcl path="C:\ContosoUniversity\ContosoUniversity\obj\Release\Package\PackageTmp" setAclUser="anonymousAuthenticationUser" setAclResourceType="Directory" /&gt;
  &lt;setAcl path="C:\ContosoUniversity\ContosoUniversity\obj\Release\Package\PackageTmp\App_Data" setAclResourceType="Directory" setAclAccess="Write" /&gt;
  &lt;setAcl path="C:\ContosoUniversity\ContosoUniversity\obj\Release\Package\PackageTmp\Elmah" setAclResourceType="Directory" setAclAccess="Read,Write" /&gt;
&lt;/sitemanifest&gt;</pre>
        <p>
This isn't all you need to do, however, because the permissions actually need to be
set on the folder in the destination application, not the folder in the deployment
package. That's why the second <code>Target</code> element is needed. The second <code>Target</code> element
("DeclareCustomParameters") creates a user-defined Web Deploy parameter
named <code>ElmahSetAclParam</code>. The value of this parameter will change the value
of the <code>setAcl</code> path at deploy time. The<code>DefaultValue</code> element
of the <code>ElmahSetAclParam</code> parameter sets the value that will be used when
you are deploying by creating and installing a deployment package; the <code>Value</code> element
sets the value that will be used when you are publishing without using a deployment
package.
</p>
        <p>
If you are using a deployment package, the actual path to the destination folder isn't
known until the package is installed. Therefore the default value of this parameter
is set using an MSDeploy parameter that resolves to the name of a system-defined Web
Deploy parameter:
</p>
        <pre class="brush: xml;">&lt;DefaultValue&gt;{$(_MsDeployParameterNameForContentPath)}/Elmah&lt;/DefaultValue&gt;</pre>
        <p>
When the package is created, <code>_MsDeployParameterNameForContentPath</code> is
translated into "{IIS Web Application Name}", so the actual default value
becomes "{IIS Web Application Name}/Elmah". When the package is installed,
the value of that Web Deploy parameter is the path of the destination root folder,
and so as a result the <code>ElmahSetAclParam</code> parameter resolves to the physical
path of the destination <em>Elmah</em> folder (for example: <em>C:\inetpub\wwwroot\ContosoUniversity\Elmah</em>).
That path then replaces the package's physical path for the Elmah <code>setAcl</code> element
in the source manifest.
</p>
        <p>
When you publish the project rather than using a deployment package, the <code>Value</code> element
instead of the <code>DefaultValue</code> element provides the value for the <code>ElmahSetAclParam</code> parameter.
In that case, you are deploying from Visual Studio, and Visual Studio has the actual
destination path value in an MSBuild property, so the <code>Value</code> element can
specify that MSBuild property directly and does not need to use a Web Deploy variable:
</p>
        <pre class="brush: xml;">&lt;Value&gt;$(_DestinationContentPath)/Elmah&lt;/Value&gt;</pre>
        <p>
The "Hidden" value in the <code>Tags</code> element prevents the <code>ElmahSetAclParam</code> parameter
from being displayed in the IIS Manager UI if you use IIS Manager to install the package.
The UI doesn't have to show the value, because a user never needs to change it manually.
</p>
        <pre class="brush: xml;">&lt;Tags&gt;Hidden&lt;/Tags&gt;</pre>
        <h3>Adding More Folders
</h3>
        <p>
You can add more folders by adding <code>ItemGroup</code> elements. The following
example builds on the earlier one by also granting Read permission for the <em>bin</em> folder
to the NETWORK SERVICE account. (This is required in some cases for SQL Server Compact.)
Notice that in order to specify the account to which access is granted, "setAclUser"
was added to the <code>&lt; AdditionalProviderSettings&gt;</code> element, and a <code>&lt;SetAclUser&gt;</code> element
specifying NETWORK SERVICE was added.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;

    &lt;Target Name="SetupCustomAcls" AfterTargets="AddIisSettingAndFileContentsToSourceManifest"&gt;
        &lt;ItemGroup&gt;
            &lt;MsDeploySourceManifest Include="setAcl"&gt;
                &lt;Path&gt;$(_MSDeployDirPath_FullPath)\Elmah&lt;/Path&gt;
                &lt;setAclAccess&gt;Read,Write&lt;/setAclAccess&gt;
                &lt;setAclResourceType&gt;Directory&lt;/setAclResourceType&gt;
                &lt;AdditionalProviderSettings&gt;setAclResourceType;setAclAccess&lt;/AdditionalProviderSettings&gt;
            &lt;/MsDeploySourceManifest&gt;
            &lt;MsDeploySourceManifest Include="setAcl"&gt;
                &lt;Path&gt;$(_MSDeployDirPath_FullPath)\bin&lt;/Path&gt;
                &lt;setAclUser&gt;NETWORK SERVICE&lt;/setAclUser&gt;
                &lt;setAclAccess&gt;Read&lt;/setAclAccess&gt;
                &lt;setAclResourceType&gt;Directory&lt;/setAclResourceType&gt;
                &lt;AdditionalProviderSettings&gt;setAclUser;setAclResourceType;setAclAccess&lt;/AdditionalProviderSettings&gt;
            &lt;/MsDeploySourceManifest&gt;
        &lt;/ItemGroup&gt;
    &lt;/Target&gt;

    &lt;Target Name="DeclareCustomParameters" AfterTargets="AddIisAndContentDeclareParametersItems"&gt;
        &lt;ItemGroup&gt;
            &lt;MsDeployDeclareParameters Include="ElmahSetAclParam"&gt;
                &lt;Kind&gt;ProviderPath&lt;/Kind&gt;
                &lt;Scope&gt;setAcl&lt;/Scope&gt;
                &lt;Match&gt;^$(_EscapeRegEx_MSDeployDirPath)\\Elmah$&lt;/Match&gt;
                &lt;Description&gt;Add write permission to the Elmah folder.&lt;/Description&gt;
                &lt;DefaultValue&gt;{$(_MsDeployParameterNameForContentPath)}/Elmah&lt;/DefaultValue&gt;
                &lt;Value&gt;$(_DestinationContentPath)/Elmah&lt;/Value&gt;
                &lt;Tags&gt;Hidden&lt;/Tags&gt;
                &lt;Priority&gt;$(VsSetAclPriority)&lt;/Priority&gt;
                &lt;ExcludeFromSetParameter&gt;True&lt;/ExcludeFromSetParameter&gt;
            &lt;/MsDeployDeclareParameters&gt;
            &lt;MsDeployDeclareParameters Include="BinSetAclParam"&gt;
                &lt;Kind&gt;ProviderPath&lt;/Kind&gt;
                &lt;Scope&gt;setAcl&lt;/Scope&gt;
                &lt;Match&gt;^$(_EscapeRegEx_MSDeployDirPath)\\Bin$&lt;/Match&gt;
                &lt;Description&gt;Add read permission to the bin folder.&lt;/Description&gt;
                &lt;DefaultValue&gt;{$(_MsDeployParameterNameForContentPath)}/bin&lt;/DefaultValue&gt;
                &lt;Value&gt;$(_DestinationContentPath)/bin&lt;/Value&gt;
                &lt;Tags&gt;Hidden&lt;/Tags&gt;
                &lt;Priority&gt;$(VsSetAclPriority)&lt;/Priority&gt;
                &lt;ExcludeFromSetParameter&gt;True&lt;/ExcludeFromSetParameter&gt;
            &lt;/MsDeployDeclareParameters&gt;
        &lt;/ItemGroup&gt;
    &lt;/Target&gt;
    
&lt;/Project&gt;</pre>
        <h3>.targets File Caching in Visual Studio
</h3>
        <p>
Setting up .targets files is like writing code -- rarely do you get everything right
the first time. If you do make a mistake that you have to fix, you should be aware
that Visual Studio caches <em>target</em> files. This means that every time you change
a <em>.targets</em> file, you must exit Visual Studio and restart it before you rebuild
the package in order to see the effect of your change. This is not an issue if you
create packages using the command line.
</p>
        <h3>Making Changes that Affect Parameters in Packages
</h3>
        <p>
Visual Studio will not rebuild a package if it cannot determine that a change has
been made, and changes that affect Web Deploy parameters are sometimes not recognized
as changes. Therefore, if you make any changes that affect parameters in the source
manifest, it's best to select <strong>Clean Solution</strong> from the <strong>Build</strong> menu
in order to delete the contents of the <em>Package</em> folder before you rebuild
the package.
</p>
        <p>
Sayed Ibrahim Hashimi – <a href="http://twitter.com/#!/sayedihashimi" target="_blank">@SayedIHashimi</a></p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=3d4f59f9-55bf-4b7b-809f-da6ef4774f4c" />
      </div>
    </content>
  </entry>
  <entry>
    <title>App.config transform Visual Studio Add in</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/08/17/AppconfigTransformVisualStudioAddIn.aspx" />
    <id>http://sedodream.com/PermaLink,guid,4f8fb902-f71e-42d6-8c41-86395a415be2.aspx</id>
    <published>2011-08-17T01:25:37.9370871-04:00</published>
    <updated>2011-08-17T01:25:37.9370871-04:00</updated>
    <category term="MSBuild" label="MSBuild" scheme="http://sedodream.com/CategoryView,category,MSBuild.aspx" />
    <category term="Visual Studio 2010" label="Visual Studio 2010" scheme="http://sedodream.com/CategoryView,category,VisualStudio2010.aspx" />
    <category term="XDT" label="XDT" scheme="http://sedodream.com/CategoryView,category,XDT.aspx" />
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
When I talk to people about the XDT (web.config) transforms that web projects support
for package/publish one of the most common questions is “Does this work for non-web
projects?” Unfortunately the answer is No, but myself and a friend of mine (Chuck
England) have created a Visual Studio add in which enables just this. You can find
it in the Visual Studio gallery under the name <a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5" target="_blank">SlowCheetah
– XML Transforms</a>. Here is an overview of the features of the add in.
</p>
        <ol>
          <li>
Add tooling to desktop project to create XDT transforms</li>
          <li>
Transform app.config for desktop projects based on build configuration</li>
          <li>
Transform any XML file to the output folder base on build configuration</li>
          <li>
Add tooling to enable previewing XDT transforms</li>
          <li>
For web projects easily transform other XML files during package/publish</li>
        </ol>
        <p>
After you install the add in you will get the following menu item when you right click
any XML file.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/Add-Transform01_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Add-Transform01" border="0" alt="Add-Transform01" src="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/Add-Transform01_thumb.png" width="347" height="241" />
          </a>
        </p>
        <p>
For each build configuration defined you will get a transform created as a child item.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/App-Config_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="App-Config" border="0" alt="App-Config" src="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/App-Config_thumb.png" width="215" height="53" />
          </a>
        </p>
        <p>
These files are stub XDT transforms. You can place your transform content in those
files and they will be executed when you debug/run your application. For example if
your app.config contained the following.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
  &lt;appSettings&gt;
    &lt;add key="appName" value="WPF Demo-Debug-default"/&gt;
    &lt;add key="url" value="http://localhost:8080/Default/"/&gt;
    &lt;add key="email" value="demo-default@contoso.com"/&gt;
  &lt;/appSettings&gt;

  &lt;connectionStrings&gt;
    &lt;clear /&gt;
    &lt;add name="RecordsDb" connectionString=".\SQLExpress;Initial Catalog=RecordsDb-Default;Integrated Security=true"/&gt;
  &lt;/connectionStrings&gt;

&lt;/configuration&gt;</pre>
        <p>
And your app.debug.config contained
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;!-- For more information on using transformations 
     see the web.comfig examples at http://go.microsoft.com/fwlink/?LinkId=214134. --&gt;
&lt;configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"&gt;

  &lt;appSettings&gt;
    &lt;add key="appName" value="WPF Demo-Debug" xdt:Transform="Replace" xdt:Locator="Match(key)"/&gt;
    &lt;add key="url" value="http://localhost:8080/" xdt:Transform="Replace" xdt:Locator="Match(key)"/&gt;
    &lt;add key="email" value="debug@contoso.com" xdt:Transform="Replace" xdt:Locator="Match(key)"/&gt;
  &lt;/appSettings&gt;

  &lt;connectionStrings&gt;
    &lt;add name="RecordsDb" connectionString=".\SQLExpress;Initial Catalog=RecordsDb;Integrated Security=true"
         xdt:Transform="Replace" xdt:Locator="Match(name)"/&gt;
  &lt;/connectionStrings&gt;

&lt;/configuration&gt;</pre>
        <p>
When you run your application the config file created will contain the following.
</p>
        <pre class="brush: xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;configuration&gt;
  &lt;appSettings&gt;
    &lt;add key="appName" value="WPF Demo-Debug"/&gt;
    &lt;add key="url" value="http://localhost:8080/"/&gt;
    &lt;add key="email" value="debug@contoso.com"/&gt;
  &lt;/appSettings&gt;

  &lt;connectionStrings&gt;
    &lt;clear/&gt;
    &lt;add name="RecordsDb" connectionString=".\SQLExpress;Initial Catalog=RecordsDb;Integrated Security=true"/&gt;
  &lt;/connectionStrings&gt;

&lt;/configuration&gt;</pre>
        <h3>Transforming other files
</h3>
        <p>
You are not limited to transforming app.config, you can transform any XML file. When
you create a transform for an arbitrary XML file when you run your application the
transformed XML file will be dropped into the output (bin) folder of your application.
</p>
        <h3>Previewing Transforms
</h3>
        <p>
You can easily preview transform results as well. After you have created the transform
file you can right click on it and select Preview Transform.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/Preview-Transform-Command_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Preview-Transform-Command" border="0" alt="Preview-Transform-Command" src="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/Preview-Transform-Command_thumb.png" width="325" height="239" />
          </a>
        </p>
        <p>
After you click it you should see the following.
</p>
        <p>
          <a href="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/Preview-Transform-Diff_2.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Preview-Transform-Diff" border="0" alt="Preview-Transform-Diff" src="http://sedodream.com/content/binary/Windows-Live-Writer/eb1580ca95bc_136F0/Preview-Transform-Diff_thumb.png" width="944" height="484" />
          </a>
        </p>
        <p>
 
</p>
        <p>
I hope you guys find this useful. Let me know if you have any feedback on this!
</p>
        <p>
          <em>
            <strong>Note: This add in was created by me and a friend of mine, these are not
created nor supported by Microsoft.</strong>
          </em>
        </p>
        <p>
Sayed Ibrahim Hashimi – <a href="http://twitter.com/#!/sayedihashimi" target="_blank">@sayedihashimi</a></p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=4f8fb902-f71e-42d6-8c41-86395a415be2" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Property Functions: GetFolderPath</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/03/21/PropertyFunctionsGetFolderPath.aspx" />
    <id>http://sedodream.com/PermaLink,guid,a20039d2-0ae3-484e-a1b3-ebd8855719f0.aspx</id>
    <published>2011-03-20T21:27:44.3814406-04:00</published>
    <updated>2011-03-20T21:30:27.121088-04:00</updated>
    <category term="MSBuild" label="MSBuild" scheme="http://sedodream.com/CategoryView,category,MSBuild.aspx" />
    <category term="MSBuild 4.0" label="MSBuild 4.0" scheme="http://sedodream.com/CategoryView,category,MSBuild40.aspx" />
    <category term="Visual Studio 2010" label="Visual Studio 2010" scheme="http://sedodream.com/CategoryView,category,VisualStudio2010.aspx" />
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
Today someone sent me an email asking how to call the <a href="http://msdn.microsoft.com/en-us/library/14tx8hby.aspx" target="_blank">System.Environment.GetFolderPath</a> method
passing in the value of <a href="http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx" target="_blank">MyDocuments</a> for
the value of the folder parameter. I was expecting the below to do the trick.
</p>
        <pre class="brush: xml;">&lt;Project ToolsVersion="4.0" 
         DefaultTargets="Demo" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;

  &lt;PropertyGroup&gt;
    &lt;Tempfile02&gt;$([System.Environment]::GetFolderPath(System.Environment.SpecialFolder.MyDocuments))&lt;/Tempfile02&gt;
  &lt;/PropertyGroup&gt;

  &lt;Target Name="Demo"&gt;
    &lt;Message Text="TempFile01: $(TempFile02)"/&gt;
  &lt;/Target&gt;

&lt;/Project&gt;</pre>
        <p>
To my surprise I was faced with the following error.
</p>
        <p>
          <font face="Courier New">Build started 3/20/2011 6:20:36 PM.</font>
        </p>
        <p>
          <font face="Courier New">Project "C:\temp\_NET\msbuild\PropFunction01.proj"
on node 1 (default targets).</font>
        </p>
        <p>
          <font face="Courier New">C:\temp\_NET\msbuild\PropFunction01.proj(20,5): error MSB4186:
Invalid static method invocation syntax: "[System.Environment]::GetFolderPath(System.Environment.Spec
ialFolder.MyDocuments)". Requested value 'System.Environment.MyDocuments' was
not found. Static method invocation should be of the form: $([FullTypeName]::Method()),
e.g. $([System.IO.Path]::Combine(`a`, `b`)).</font>
        </p>
        <p>
          <font face="Courier New">Done Building Project "C:\temp\_NET\msbuild\PropFunction01.proj"
(default targets) -- FAILED.</font>
        </p>
        <p>
          <font face="Courier New">Build FAILED.</font>
        </p>
        <p>
So I sent an email to the MSBuild team asking “WTF why doesn’t this work?!”, and Dan
Moseley (a lead dev there) sent me a snippet that worked, its below.
</p>
        <pre class="brush: xml;">&lt;Project ToolsVersion="4.0" DefaultTargets="Demo" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;

  &lt;PropertyGroup&gt;
    &lt;Tempfile02&gt;$([System.Environment]::GetFolderPath(SpecialFolder.MyDocuments))&lt;/Tempfile02&gt;
  &lt;/PropertyGroup&gt;

  &lt;Target Name="Demo"&gt;
    &lt;Message Text="TempFile01: $(TempFile02)"/&gt;
  &lt;/Target&gt;

&lt;/Project&gt;</pre>
        <p>
 
</p>
        <p>
In that snippet instead of using the fully qualified class name of <font face="Courier New">System.Environment.SpecialFolder.MyDocuments</font>,
for some reason you have to use the shortened name of just SpecialFolder.MyDocuments.
It seems like a bug to me, but at least there is a work around!
</p>
        <h4>Resources
</h4>
        <ul>
          <li>
            <a href="http://sedodream.com/2010/03/07/MSBuild40PropertyFunctionsPart1.aspx" target="_blank">Property
Functions Part 1</a>
          </li>
          <li>
            <a href="http://msdn.microsoft.com/en-us/library/dd633440.aspx" target="_blank">Property
Functions MSDN Reference</a>
          </li>
          <li>
            <a href="http://blogs.msdn.com/b/msbuild/archive/2010/04/02/msbuild-property-functions.aspx" target="_blank">Property
Functions: MSBuild Team Blog</a>
          </li>
        </ul>
        <p>
Sayed Ibrahim Hashimi – <a href="http://twitter.com/sayedihashimi" target="_blank">@sayedihashimi</a></p>
        <img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=a20039d2-0ae3-484e-a1b3-ebd8855719f0" />
      </div>
    </content>
  </entry>
  <entry>
    <title>How to compress CSS/JavaScript before publish/package</title>
    <link rel="alternate" type="text/html" href="http://sedodream.com/2011/02/25/HowToCompressCSSJavaScriptBeforePublishpackage.aspx" />
    <id>http://sedodream.com/PermaLink,guid,487f5f26-2d6f-4deb-9d5d-24b500cab3ff.aspx</id>
    <published>2011-02-25T00:21:44.528-05:00</published>
    <updated>2011-02-25T14:43:20.7188535-05:00</updated>
    <category term="Deployment" label="Deployment" scheme="http://sedodream.com/CategoryView,category,Deployment.aspx" />
    <category term="MSDeploy" label="MSDeploy" scheme="http://sedodream.com/CategoryView,category,MSDeploy.aspx" />
    <category term="Web Publishing Pipeline" label="Web Publishing Pipeline" scheme="http://sedodream.com/CategoryView,category,WebPublishingPipeline.aspx" />
    <author>
      <name>Ibrahim</name>
    </author>
    <content type="html">&lt;p&gt;
Today I saw a post on stackoverflow.com asking &lt;a href="http://stackoverflow.com/q/5043504/105999" target="_blank"&gt;Using
Microsoft AJAX Minifier with Visual Studio 2010 1-click publish&lt;/a&gt;. This is a response
to that question. The Web Publishing Pipeline is pretty extensive so it is easy for
us to hook in to it in order to perform operation such as these. One of those extension
points, as we’ve blogged about before, is creating a .wpp.targets file. If you create
a file in the same directory of your project with the name {ProjectName}.wpp.targets
then that file will automatically be imported and included in the build/publish process.
This makes it easy to edit your build/publish process without always having to edit
the project file itself. I will use this technique to demonstrate how to compress
the CSS &amp; JavaScript files a project contains before it is published/packaged.
&lt;/p&gt;
&lt;p&gt;
Eventhough the question specifically states Microsoft AJAX Minifier I decided to use
the compressor contained in Packer.NET (link in resources section). I did this because
when I looked at the MSBuild task for the AJAX Minifier it didn’t look like I could
control the output location of the compressed files. Instead it would simply write
to the same folder with an extension like .min.cs or .min.js. In any case, when you
publish/package your Web Application Project (WAP) the files are copied to a temporary
location before the publish/package occurs. The default value for this location is
obj\{Configuration}\Package\PackageTmp\ where {Configuration} is the build configuration
that you are currently using for your WAP. So what we need to do is to allow the WPP
to copy all the files to that location and then after that we can compress the CSS
and JavaScript that goes in that folder. The target which copies the files to that
location is &lt;strong&gt;CopyAllFilesToSingleFolderForPackage&lt;/strong&gt;. (To learn more
about these targets take a look at the file %Program Files (x86)%\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets.)
To make our target run after this target we can use the MSBuild AfterTargets attribute.
The project that I created to demonstrate this is called CompressBeforePublish, because
of that I create a new file named CompressBeforePublish.wpp.targets to contain my
changes.
&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;
&lt;Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;
&lt;UsingTask taskname="SmallSharpTools.Packer.MSBuild.Packer" assemblyfile="$(MSBuildThisFileDirectory)..\Contrib\SmallSharpTools.Packer\SmallSharpTools.Packer.dll" /&gt;
&lt;!-- This target will run after the files are copied to PackageTmp folder --&gt;
&lt;Target name="CompressJsAndCss" aftertargets="CopyAllFilesToSingleFolderForPackage"&gt;
&lt;!-- Discover files to compress --&gt;
&lt;ItemGroup&gt;
&lt;_JavaScriptFiles include="$(_PackageTempDir)\Scripts\**\*.js" /&gt;
&lt;_CssFiles include="$(_PackageTempDir)\Content\**\*.css" /&gt;
&lt;/ItemGroup&gt;
&lt;Message text="Compressing JavaScript files" importance="high" /&gt;
&lt;!-- 
      Compress the JavaScript files. 
      Not the usage of %(JavaScript.Identity which causes this task to run once per
      .js file in the JavaScriptFiles item list.
      For more info on batching: http://sedotech.com/resources#Batching
    --&gt;
&lt;Packer inputfiles="%(_JavaScriptFiles.Identity)" outputfilename="@(_JavaScriptFiles-&gt;'$(_PackageTempDir)\Scripts\%(RecursiveDir)%(Filename)%(Extension)')" mode="JSMin" verbose="false" condition=" '@(_JavaScriptFiles)' != ''" /&gt;
&lt;Message text="Compressing CSS files" importance="high" /&gt;
&lt;Packer inputfiles="%(_CssFiles.Identity)" outputfilename="@(_CssFiles-&gt;'$(_PackageTempDir)\Content\%(RecursiveDir)%(Filename)%(Extension)')" mode="CSSMin" verbose="false" condition=" '@(_CssFiles)' != '' " /&gt;
&lt;/Target&gt;
&lt;/Project&gt;
&lt;/pre&gt;
&lt;p&gt;
Here I’ve created one target, CompressJsAndCss, and I have included AfterTargets=”CopyAllFilesToSingleFolderForPackage”
which causes it to be executed after CopyAllFilesToSingleFolderForPackage. Inside
this target I do two things, gather the files which need to be compressed and then
I compress them.
&lt;/p&gt;
&lt;h5&gt;1. Gather files to be compressed
&lt;/h5&gt;
&lt;pre class="brush: xml;"&gt;
&lt;ItemGroup&gt;
&lt;_JavaScriptFiles include="$(_PackageTempDir)\Scripts\**\*.js" /&gt;
&lt;_CssFiles include="$(_PackageTempDir)\Content\**\*.css" /&gt;
&lt;/ItemGroup&gt;
&lt;/pre&gt;
&lt;p&gt;
Here I use an item list for both JavaScript files as well as CSS files. Notice that
I am using the _PackageTempDir property to pickup .js &amp; .css files inside the temporary
folder where the files are written to be packaged. The reason that I’m doing that
instead of picking up source files is because my build may be outputting other .js
&amp; .css files and which are going to be published. &lt;em&gt;Note: since the property _PackageTempDir
starts with an underscore it is not guaranteed to behave (or even exist) in future
versions&lt;/em&gt;.
&lt;/p&gt;
&lt;h5&gt;2. Compress files
&lt;/h5&gt;
&lt;p&gt;
I use the Packer task to compress the .js and .css files. For both sets of files the
usage is pretty similar so I will only look at the first usage.
&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;
&lt;Packer inputfiles="%(_JavaScriptFiles.Identity)" outputfilename="@(_JavaScriptFiles-&gt;'$(_PackageTempDir)\Scripts\%(RecursiveDir)%(Filename)%(Extension)')" mode="JSMin" verbose="false" condition=" '@(_JavaScriptFiles)' != ''" /&gt;
&lt;/pre&gt;
&lt;p&gt;
Here the task is fed all the .js files for compression. Take a note how I passed the
files into the task using, %(_JavaScriptFiles.Identity), in this case what that does
is to cause this task to be executed once per .js file. &lt;em&gt;The %(abc.def) syntax
invokes batching, if you are not familiar with batching please see below.&lt;/em&gt; For
the value of the output file I use the _PackageTempDir property again. In this case
since the item already resides there I could have simplified that to be @(_JavaScriptFiles-&gt;’%(FullPath)’)
but I thought you might find that expression helpful in the case that you are compressing
files which do not already exist in the _PackageTempDir folder.
&lt;/p&gt;
&lt;p&gt;
Now that we have added this target to the .wpp.targets file we can publish/package
our web project and it the contained .js &amp; .css files will be compressed. &lt;em&gt;Note:
Whenever you modify the .wpp.targets file you will have to unload/reload the web project
so that the changes are picked up, Visual Studio caches your projects.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
In the image below you can see the difference that compressing these files made.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://sedodream.com/content/binary/Windows-Live-Writer/How-to-compress-CSSJavaScript-before-pub_13DD2/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://sedodream.com/content/binary/Windows-Live-Writer/How-to-compress-CSSJavaScript-before-pub_13DD2/image_thumb.png" width="738" height="416" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
You can download the entire project below, as well as take a look at some other resources
that I have that you might be interested in.
&lt;/p&gt;
&lt;p&gt;
Sayed Ibrahim Hashimi
&lt;/p&gt;
&lt;h5&gt;Resources
&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://sedotech.com/content/samples/CompressBeforePublish.zip"&gt;http://sedotech.com/content/samples/CompressBeforePublish.zip&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
&lt;a title="http://sedotech.com/resources#batching" href="http://sedotech.com/resources#batching"&gt;http://sedotech.com/resources#batching&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://freetodev.wordpress.com/2009/06/24/msbuild-4-0-beforetargets-and-aftertargets/" target="_blank"&gt;MSBuild
BeforeTargets/AfterTargets&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
&lt;a title="http://sedodream.com/2010/08/15/WebDeploymentToolMSDeployHowToExcludeFilesFromPackageBasedOnConfiguration.aspx" href="http://sedodream.com/2010/08/15/WebDeploymentToolMSDeployHowToExcludeFilesFromPackageBasedOnConfiguration.aspx"&gt;•Web
Deploy: How to exclude files from package based on Configuration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://svn.offwhite.net/trac/SmallSharpTools.Packer/" target="_blank"&gt;Packer.NET&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://sedodream.com/aggbug.ashx?id=487f5f26-2d6f-4deb-9d5d-24b500cab3ff" /&gt;</content>
  </entry>
</feed>
