<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Re-inventing The Wheel</title><link>http://blogs.msdn.com/mwade/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>How To: Generate publish.htm with MSBuild</title><link>http://blogs.msdn.com/mwade/archive/2009/02/28/how-to-generate-publish-htm-with-msbuild.aspx</link><pubDate>Sun, 01 Mar 2009 02:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9451445</guid><dc:creator>mwade</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/mwade/comments/9451445.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=9451445</wfw:commentRss><description>&lt;P&gt;One of the features Visual Studio provides when publishing is the generation of a &lt;A href="http://www.familywade.net/applications/MoneyMatrix/publish.htm" mce_href="http://www.familywade.net/applications/MoneyMatrix/publish.htm"&gt;web page&lt;/A&gt; that serves as an installation entry point of a ClickOnce application. It describes some information about the application, application requirements, and even includes a jscript that will bypass the bootstrapper if the required version of the .NET Framework is already installed. The web page is generated as part of the publishing phase (as opposed to the manifest generation phase) when the publish action is taken publishing within Visual Studio. Manifest generation is msbuild-based, while the publish phase is not.&lt;/P&gt;
&lt;P&gt;There are several circumstances when you want thte web page created as part of the manifest generation process instead of the publish process. For example, when manifests are generated as part of an automated build process. Perhaps you want to use your own template for the web page, but still want some aspects of the page to be dynamically set. Or, matbe you want to translate the template into a different language, be it one available from a Visual Studio language pack, or one not supplied by Microsoft. Whatever your reason, this blog post will show you one way to get that done.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Background: How publish.htm is generated&lt;/B&gt;&lt;/P&gt;
&lt;P&gt;Let's begin by looking at the template used to generate the web page. It is embedded as a resource in Microsoft.ViualStudio.Publish.dll, available in the GAC. I have attached it at the end of the post, but it is an XSL style sheet. Here's a little snippet:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#2b91af&gt;xsl:template&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;match&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PageData&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;HTML&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;HEAD&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
      &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TITLE&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#2b91af&gt;xsl:value-of&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;select&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ProductName&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;/&amp;gt; 
      &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TITLE&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
      &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;META&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;HTTP-EQUIV&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Content-Type&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;CONTENT&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;text/html; charset=utf-8&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The stylesheet reads info out of an XML fragment, of which &lt;CODE&gt;PageData&lt;/CODE&gt; is the root element. A scan of the stylesheet shows that the data used to transform the stylesheet may look something like this:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PageData&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;xmlns:xsi&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;xmlns:xsd&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;http://www.w3.org/2001/XMLSchema&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ApplicationVersion&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;1.0.0.0&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ApplicationVersion&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;InstallUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;ConsoleApplication.application&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;InstallUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ProductName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;ConsoleApplication&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ProductName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublisherName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Mike Wade&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublisherName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;SupportUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;http://blogs.msdn.com/mwade&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;SupportUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Prerequisites&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Prerequisite&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;.NET Framework 3.5&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Prerequisite&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Prerequisite&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Windows Installer 3.1&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Prerequisite&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Prerequisites&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;RuntimeVersion&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;2.0.0&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;RuntimeVersion&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;BootstrapperText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;The following prerequisites are required:&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;BootstrapperText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ButtonLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Install&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ButtonLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;BypassText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;If these components are already installed, you can {launch} the application now. Otherwise, click the button below to install the prerequisites and run the application.&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;BypassText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;HelpText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;ClickOnce and .NET Framework Resources&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;HelpText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;HelpUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;http://msdn.microsoft.com/clickonce&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;HelpUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;NameLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Name:&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;NameLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublisherLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Publisher:&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublisherLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;SupportText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Mike Wade Customer Support&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;SupportText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;VersionLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Version:&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;VersionLabel&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PageData&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The xml input contains 3 basic types of information:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Application specific information (publisher, product, install, etc.)&lt;/LI&gt;
&lt;LI&gt;Application prerequisite information (bootsrapper packages installed, a .NET Framework runtime used by the jscript)&lt;/LI&gt;
&lt;LI&gt;Static strings read from Microsoft.VisualStudio.Publish.dll&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;B&gt;A build task to create publish.htm&lt;/B&gt;&lt;/P&gt;Let's create a build task that will create the publish web page. &lt;PRE&gt;&lt;FONT color=#0000ff&gt;namespace&lt;/FONT&gt; CreatePublishWebPage 
{ 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;class&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;CreatePublishWebPage&lt;/FONT&gt; : &lt;FONT color=#2b91af&gt;Task&lt;/FONT&gt; 
    { 
    } 
}
&lt;/PRE&gt;
&lt;P&gt;This task will be performing the XML transform. Most of the work that the task does will be to populate the page data to get it ready for serialization and then used in the transform. The page data is declared like this:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;struct&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt; 
{ 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; ApplicationVersion; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; InstallUrl; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; ProductName; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; PublisherName; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; SupportUrl; 
 
    [&lt;FONT color=#2b91af&gt;XmlArray&lt;/FONT&gt;()] 
    [&lt;FONT color=#2b91af&gt;XmlArrayItem&lt;/FONT&gt;(&lt;FONT color=#a31515&gt;"Prerequisite"&lt;/FONT&gt;)] 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;[] Prerequisites; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; RuntimeVersion; 
 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; BootstrapperText; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; ButtonLabel; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; BypassText; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; HelpText; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; HelpUrl; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; NameLabel; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; PublisherLabel; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; SupportText; 
    &lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; VersionLabel; 
}
&lt;/PRE&gt;
&lt;P&gt;The first 5 items are all part of the deploy manifest. It would be possible to populate the information with the project properties used to build the manifest, or the information could be pulled directly from the manifest. Let's choose the latter. One slight difference is that the publisher and product are automatically populated when the manifest is generated, even if the properties are blank.&lt;/P&gt;
&lt;P&gt;The prerequisites will be taken from the bootrapper build information, both the bootstraper package items as well as the bootstrapper enabled property. The RuntimeVersion data is only used when the jscript is written into the web page. There are 2 potential sources for this version: either by inspecting the list of bootstrapper packages, or by inspecting the application manifest's prerequisites. VisualStudio uses the former, but this task will use the latter: its a more accurate reflection of the true requirements of the application.&lt;/P&gt;
&lt;P&gt;Finally, the other information will be part of the build tasks resources, which I also pulled out of Microsoft.VisualStudio.Publish.dll&lt;/P&gt;
&lt;P&gt;With this in mind, it is easy to stub out the task, like this:&lt;/P&gt;&lt;PRE&gt;[&lt;FONT color=#2b91af&gt;Required&lt;/FONT&gt;] 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; ApplicationManifestFileName { &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt;; &lt;FONT color=#0000ff&gt;set&lt;/FONT&gt;; } 
 
[&lt;FONT color=#2b91af&gt;Required&lt;/FONT&gt;] 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; DeploymentManifestFileName { &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt;; &lt;FONT color=#0000ff&gt;set&lt;/FONT&gt;; } 
 
[&lt;FONT color=#2b91af&gt;Required&lt;/FONT&gt;] 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; BootstrapperEnabled { &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt;; &lt;FONT color=#0000ff&gt;set&lt;/FONT&gt;; } 
 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;ITaskItem&lt;/FONT&gt;[] BootstrapperPackages { &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt;; &lt;FONT color=#0000ff&gt;set&lt;/FONT&gt;; } 
 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; TemplateFileName { &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt;; &lt;FONT color=#0000ff&gt;set&lt;/FONT&gt;; } 
 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; OutputFileName { &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt;; &lt;FONT color=#0000ff&gt;set&lt;/FONT&gt;; } 
 
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;override&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; Execute() 
{ 
    &lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt; data = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt;(); 
 
    WriteManifestInfo(&lt;FONT color=#0000ff&gt;ref&lt;/FONT&gt; data); 
    &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (BootstrapperEnabled) 
    { 
        WriteBootstrapperInfo(&lt;FONT color=#0000ff&gt;ref&lt;/FONT&gt; data); 
    } 
    WriteStaticText(&lt;FONT color=#0000ff&gt;ref&lt;/FONT&gt; data); 
 
    XmlTransform(data); 
     
    &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;; 
}
&lt;/PRE&gt;
&lt;P&gt;Now, let's get to th actual meat of the task, starting with &lt;CODE&gt;WriteManifestInfo&lt;/CODE&gt;. The code will use the &lt;CODE&gt;ManifestUtilities&lt;/CODE&gt; API to directly access the appropriate properties from &lt;CODE&gt;DeployManifest&lt;/CODE&gt;. &lt;CODE&gt;ManifestUtilities&lt;/CODE&gt; is defined in Microsoft.Build.Tasks.v3.5.dll, which unfortunately only exists in the GAC. You will have to copy it out of the GAC in order to add a reference to it. The code to populate the page data is not terribly tricky:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt; Microsoft.Build.Tasks.Deployment.ManifestUtilities;

&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;DeployManifest&lt;/FONT&gt; deployManifest = &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;; 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;DeployManifest&lt;/FONT&gt; DeployManifest 
{ 
    &lt;FONT color=#0000ff&gt;get&lt;/FONT&gt; 
    { 
        &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (deployManifest == &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;) 
        { 
            deployManifest = (&lt;FONT color=#2b91af&gt;DeployManifest&lt;/FONT&gt;)&lt;FONT color=#2b91af&gt;ManifestReader&lt;/FONT&gt;.ReadManifest(&lt;FONT color=#0000ff&gt;this&lt;/FONT&gt;.DeploymentManifestFileName, &lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;); 
        } 
        &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; deployManifest; 
    } 
} 
 
 &lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; WriteManifestInfo(&lt;FONT color=#0000ff&gt;ref&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt; data) 
{ 
    data.ApplicationVersion = DeployManifest.AssemblyIdentity.Version; 
    data.InstallUrl = &lt;FONT color=#2b91af&gt;Path&lt;/FONT&gt;.GetFileName(DeployManifest.SourcePath); 
    data.ProductName = DeployManifest.Product; 
    data.PublisherName = DeployManifest.Publisher; 
    data.SupportUrl = DeployManifest.SupportUrl; 
}
&lt;/PRE&gt;
&lt;P&gt;The code uses a simple accessor to access the &lt;CODE&gt;DeployManifest&lt;/CODE&gt;, and then writes appropriate information to the page data.&lt;/P&gt;
&lt;P&gt;Dealing with prerequisites is a little more complicated in. There are 3 important steps in the process:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Add a list of all installed prerequisites into the Prerequisites field&lt;/LI&gt;
&lt;LI&gt;Determine if the only prerequisites are .NET Frameowrk (or Windows Installer 3.1) only&lt;/LI&gt;
&lt;LI&gt;Determine the required framework version based on the presence of specific .NET assemblies in the application manifest&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;For this last point, the &lt;CODE&gt;WindowsBase&lt;/CODE&gt; prereq corresponds to the 3.0 framework, while &lt;CODE&gt;System.Core&lt;/CODE&gt; corresponds to the 3.5 framework. The prereqs are looked by examining the &lt;CODE&gt;AssemblyReferences&lt;/CODE&gt; of the application manifest. Now for the actual code:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt; Microsoft.Build.Tasks.Deployment.Bootstrapper;

&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;readonly&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;[] DOTNET30AssemblyIdentity = { &lt;FONT color=#a31515&gt;"WindowsBase"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"3.0.0.0"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"31bf3856ad364e35"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"neutral"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"msil"&lt;/FONT&gt; }; 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;readonly&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;[] DOTNET35AssemblyIdentity = { &lt;FONT color=#a31515&gt;"System.Core"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"3.5.0.0"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"b77a5c561934e089"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"neutral"&lt;/FONT&gt;, &lt;FONT color=#a31515&gt;"msil"&lt;/FONT&gt; }; 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;const&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; METADATA_INSTALL = &lt;FONT color=#a31515&gt;"Install"&lt;/FONT&gt;; 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;const&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; PRODUCT_CODE_DOTNET_PREFIX = &lt;FONT color=#a31515&gt;"Microsoft.Net.Framework."&lt;/FONT&gt;; 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;const&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; PRODUCT_CODE_WINDOWS_INSTALLER = &lt;FONT color=#a31515&gt;"Microsoft.Windows.Installer.3.1"&lt;/FONT&gt;;

&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; WriteBootstrapperInfo(&lt;FONT color=#0000ff&gt;ref&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt; data) 
{ 
    &lt;FONT color=#2b91af&gt;BootstrapperBuilder&lt;/FONT&gt; builder = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;BootstrapperBuilder&lt;/FONT&gt;(); 
    &lt;FONT color=#2b91af&gt;ProductCollection&lt;/FONT&gt; products = builder.Products; 
     
    &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; isDotNetOnly = &lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;; 
    &lt;FONT color=#2b91af&gt;List&lt;/FONT&gt;&amp;lt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&amp;gt; productNames = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;List&lt;/FONT&gt;&amp;lt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&amp;gt;(); 
    &lt;FONT color=#0000ff&gt;foreach&lt;/FONT&gt; (&lt;FONT color=#2b91af&gt;ITaskItem&lt;/FONT&gt; bootstrapperPackage &lt;FONT color=#0000ff&gt;in&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;this&lt;/FONT&gt;.BootstrapperPackages) 
    { 
        &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; productCode = bootstrapperPackage.ItemSpec; 
        &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; install = &lt;FONT color=#0000ff&gt;false&lt;/FONT&gt;; 
        &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt;.TryParse(bootstrapperPackage.GetMetadata(METADATA_INSTALL), &lt;FONT color=#0000ff&gt;out&lt;/FONT&gt; install); 
        &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (install) 
        { 
            &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; productName = productCode; 
            &lt;FONT color=#2b91af&gt;Product&lt;/FONT&gt; product = products.Product(productCode); 
            &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (product != &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;) 
            { 
                productName = product.Name; 
            } 
            productNames.Add(productName); 
 
            &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (!productCode.StartsWith(PRODUCT_CODE_DOTNET_PREFIX, &lt;FONT color=#2b91af&gt;StringComparison&lt;/FONT&gt;.OrdinalIgnoreCase) &amp;amp;&amp;amp; 
                !productCode.Equals(PRODUCT_CODE_WINDOWS_INSTALLER, &lt;FONT color=#2b91af&gt;StringComparison&lt;/FONT&gt;.OrdinalIgnoreCase)) 
            { 
                isDotNetOnly = &lt;FONT color=#0000ff&gt;false&lt;/FONT&gt;; 
            } 
        } 
    } 
 
    data.Prerequisites = productNames.ToArray(); 
    &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (data.Prerequisites.Length &amp;gt; 0 &amp;amp;&amp;amp; isDotNetOnly) 
    { 
        data.RuntimeVersion = GetRuntimeVersion(); 
    } 
} 
 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; GetRuntimeVersion() 
{ 
    &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt; version = &lt;FONT color=#a31515&gt;"2.0.0"&lt;/FONT&gt;; 
    &lt;FONT color=#2b91af&gt;AssemblyReference&lt;/FONT&gt; dotNet30AssemblyReference = ApplicationManifest.AssemblyReferences.Find(CreateAssemblyIdentity(DOTNET30AssemblyIdentity)); 
    &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (dotNet30AssemblyReference != &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt; &amp;amp;&amp;amp; dotNet30AssemblyReference.IsPrerequisite) 
    { 
        version = &lt;FONT color=#a31515&gt;"3.0.0"&lt;/FONT&gt;; 
    } 
    &lt;FONT color=#2b91af&gt;AssemblyReference&lt;/FONT&gt; dotNet35AssemblyReference = ApplicationManifest.AssemblyReferences.Find(CreateAssemblyIdentity(DOTNET35AssemblyIdentity)); 
    &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (dotNet35AssemblyReference != &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt; &amp;amp;&amp;amp; dotNet35AssemblyReference.IsPrerequisite) 
    { 
        version = &lt;FONT color=#a31515&gt;"3.5.0"&lt;/FONT&gt;; 
    } 
 
    &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; version; 
} 
 
&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;AssemblyIdentity&lt;/FONT&gt; CreateAssemblyIdentity(&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;[] info) 
{ 
    &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;AssemblyIdentity&lt;/FONT&gt;(info[0], info[1], info[2], info[3], info[4]);  
}
&lt;/PRE&gt;
&lt;P&gt;Getting the static text is not terribly exciting. There are only two things of note: the text for the "go" button changes depending on whether the application is installed or is online only, and the support information also incorporates the publisher name.&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; WriteStaticText(&lt;FONT color=#0000ff&gt;ref&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt; data) 
{ 
    data.BootstrapperText = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.BootstrapperText; 
    &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (deployManifest.Install) 
    { 
        data.ButtonLabel = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.InstallButtonLabel; 
    } 
    &lt;FONT color=#0000ff&gt;else&lt;/FONT&gt; 
    { 
        data.ButtonLabel = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.RunButtonLabel; 
    } 
    data.BypassText = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.BypassText; 
    data.HelpText = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.HelpText; 
    data.HelpUrl = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.HelpUrl; 
    data.NameLabel = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.NameLabel; 
    data.PublisherLabel = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.PublisherLabel; 
    data.SupportText = &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;.Format(&lt;FONT color=#2b91af&gt;CultureInfo&lt;/FONT&gt;.CurrentCulture, Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.SupportText, DeployManifest.Publisher); 
    data.VersionLabel = Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.VersionLabel; 
}
&lt;/PRE&gt;
&lt;P&gt;The last item of note is actually performing the transform, based on either a supplied template or using the default one (read from the task assembly's resources). The input is created by serializing the page data.&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; XmlTransform(&lt;FONT color=#2b91af&gt;PageData&lt;/FONT&gt; data) 
{ 
    &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (!&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;.IsNullOrEmpty(&lt;FONT color=#0000ff&gt;this&lt;/FONT&gt;.OutputFileName)) 
    { 
        &lt;FONT color=#008000&gt;// Serialize all of the web page data&lt;/FONT&gt; 
        &lt;FONT color=#2b91af&gt;XmlSerializer&lt;/FONT&gt; serializer = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;XmlSerializer&lt;/FONT&gt;(data.GetType()); 
        &lt;FONT color=#2b91af&gt;MemoryStream&lt;/FONT&gt; dataStream = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;MemoryStream&lt;/FONT&gt;(); 
        &lt;FONT color=#2b91af&gt;StreamWriter&lt;/FONT&gt; streamWriter = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;StreamWriter&lt;/FONT&gt;(dataStream); 
        serializer.Serialize(streamWriter, data); 
        dataStream.Position = 0; 
        &lt;FONT color=#2b91af&gt;XmlReader&lt;/FONT&gt; dataReader = &lt;FONT color=#2b91af&gt;XmlReader&lt;/FONT&gt;.Create(dataStream); 
 
        &lt;FONT color=#008000&gt;// Set up the transform&lt;/FONT&gt; 
        &lt;FONT color=#2b91af&gt;XmlDocument&lt;/FONT&gt; stylesheet = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;XmlDocument&lt;/FONT&gt;(); 
        &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt; (!&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;.IsNullOrEmpty(TemplateFileName)) 
        { 
            stylesheet.Load(TemplateFileName); 
        } 
        &lt;FONT color=#0000ff&gt;else&lt;/FONT&gt; 
        { 
            stylesheet.LoadXml(Properties.&lt;FONT color=#2b91af&gt;Resources&lt;/FONT&gt;.PublishPage); 
        } 
        &lt;FONT color=#2b91af&gt;XslCompiledTransform&lt;/FONT&gt; transform = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;XslCompiledTransform&lt;/FONT&gt;(); 
        transform.Load(stylesheet); 
 
        &lt;FONT color=#008000&gt;// Perform the transform, writing to the output file&lt;/FONT&gt; 
        &lt;FONT color=#0000ff&gt;using&lt;/FONT&gt; (&lt;FONT color=#2b91af&gt;XmlTextWriter&lt;/FONT&gt; outputFile = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#2b91af&gt;XmlTextWriter&lt;/FONT&gt;(&lt;FONT color=#0000ff&gt;this&lt;/FONT&gt;.OutputFileName, &lt;FONT color=#2b91af&gt;Encoding&lt;/FONT&gt;.UTF8)) 
        { 
            outputFile.Formatting = &lt;FONT color=#2b91af&gt;Formatting&lt;/FONT&gt;.Indented; 
            transform.Transform(dataReader, outputFile); 
        } 
    } 
}
&lt;/PRE&gt;&lt;B&gt;
&lt;P&gt;Using the &lt;CODE&gt;CreatePublishWebPage&lt;/CODE&gt; Task&lt;/P&gt;&lt;/B&gt;To use the task, you need only to modify your project file, overriding the "&lt;CODE&gt;AfterPublish&lt;/CODE&gt;" target: &lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;UsingTask&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;TaskName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;CreatePublishWebPage&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;AssemblyFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\\CreatePublishWebPage.dll&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;AfterPublish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;CreatePublishWebPage&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;ApplicationManifestFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)&lt;/FONT&gt;"  
                          
                        &lt;FONT color=#ff0000&gt;DeploymentManifestFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PublishDir)$(TargetDeployManifestFileName)&lt;/FONT&gt;"  
                          
                        &lt;FONT color=#ff0000&gt;BootstrapperEnabled&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BootstrapperEnabled)&lt;/FONT&gt;"  
                          
                        &lt;FONT color=#ff0000&gt;BootstrapperPackages&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(BootstrapperPackage)&lt;/FONT&gt;"  
                          
                        &lt;FONT color=#ff0000&gt;OutputFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PublishDir)$(WebPage)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The above snippet writes the publish.htm to the app.publish folder under your config's output (e.g. &lt;CODE&gt;bin\debug\app.publish&lt;/CODE&gt;). The relevant paths were pulled from the Microsoft.common.targets file. It may make sense to add a condition or 2 to the target, taking into account whether or not the build is happening from within Visual Studio (&lt;CODE&gt;BuildingInsideVisualStudio&lt;/CODE&gt;) as well as whether or not the user wants to generate a publish.htm file (&lt;CODE&gt;CreateWebPageOnPublish&lt;/CODE&gt;). Unfortunately, it appears the file is not picked up as part of the publish phase, so you may have to transport the file to its final resting place yourself.&lt;/P&gt;
&lt;P&gt;I have attached the full project as a to the end of this post.&lt;/P&gt;&lt;B&gt;
&lt;P&gt;A note about Visual Studio 2008 SP1&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;There was a little bit of change around the web page, specifically the jscript used to detect the framework. I believe the SP behavior around the .NET Framework versions was similar to what was done here, in that the jscript could actually check for 3.0, 3.5, or 3.5 SP1. It seems that the Visual Studio 2008 RTM could only deal with 2.0 of the Framework. The SP also introduced the client version of the .NET Framework. While the jscript code was updated to take that into account, the PageData is not able to properly detect that the cllient framework bootstrapper package is being used, because of the ProductName used by the client bootststrapper package. Unfortunately, I can't remember for sure, and of course the SP 1 install from MSDN doesn't seem to work on my laptop.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9451445" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/9451445.ashx" length="16538" type="application/x-zip-compressed" /></item><item><title>What's New in Visual Studio 2008 SP1 ClickOnce Tooling</title><link>http://blogs.msdn.com/mwade/archive/2008/08/29/what-s-new-in-visuall-studio-2008-sp1-clickonce-tooling.aspx</link><pubDate>Sat, 30 Aug 2008 01:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8907039</guid><dc:creator>mwade</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/mwade/comments/8907039.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=8907039</wfw:commentRss><description>&lt;P&gt;Here is a post I've been meaning to do for a while, but avoided because there is &lt;A class="" href="http://msdn.microsoft.com/en-us/library/bb386063.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb386063.aspx"&gt;some MSDN info&lt;/A&gt; on it. But a &lt;A class="" href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3803893&amp;amp;SiteID=1" target=_blank mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3803893&amp;amp;SiteID=1"&gt;recent question&lt;/A&gt; to the forums made me think that maybe it was time to talk about things that were not addressed in the document: what's &lt;B&gt;really&lt;/B&gt; new in Visual Studio 2008 SP1 (at least in respect to ClickOnce tooling). But before we start talking about what's new, let's start talking about what's old.&lt;/P&gt;
&lt;P&gt;One great thing about ClickOnce applications is that the deployment model is very declarative: simply by looking at an XML file, you can earn all sorts of things about the installation. Have you ever tried looking at an MSI file? It's pretty complicated. And that's not a knock: it's complicated because it has to be (okay, maybe a small knock). One of the items in the ClickOnce manifest are "pre-requisite assemblies", which are expressed as a preRequisite assembly dependency:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependency&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;dependencyType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;preRequisite&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;allowDelayedBinding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;assemblyIdentity&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ClassLibrary1&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;1.0.0.0&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;publicKeyToken&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;F10848788BBE80F6&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;language&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;neutral&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;processorArchitecture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;msil&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependency&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;This is stating that the application requires a specific strongly-named assembly (ClassLibrary1) in order to run. Especially noteworthy is the "dependencyType" attribute: a value of "preRequisite" means that the stated dependency must be available on the machine in order for the ClickOnce application to run. More succinctly, the assembly has to be installed to the global assembly cache. How to get the assembly into the cache is your problem.&lt;/P&gt;
&lt;P&gt;Consider the following fragment, which I took out of an application manifest that targets the 2.0 framework. For the simple application I created, this is the only prerequisite assembly listed.&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependency&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;dependencyType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;preRequisite&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;allowDelayedBinding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;assemblyIdentity&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Microsoft.Windows.CommonLanguageRuntime&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;2.0.50727.0&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependency&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;This is the one assembly dependency that breaks the rules. First of all, what is this assembly? There isn't anything in the GAC called Microsoft.Windows.CommonLanguageRuntime! Well, this particular assembly dependency is basically a code to the ClickOnce runtime engine saying that the 2.0 CLR needs to be installed in order to run the application (I won't bother to mention that this seems a little strange: since the ClickOnce runtime engine is reading the file, and the engine is only installed as part of the 2.0 Framework, it stands to reason the 2.0 CLR is there. Okay, I guess I will bother to mention it.).&lt;/P&gt;
&lt;P&gt;Another thing to notice: why is this the only dependency listed? My application has a reference to System.dll and System.Windows.Forms.dll, so shouldn't these be listed as well? The answer: probably. But as part of the manifest generation the references that are redistributed with parts of the .NET Framework are stripped from the manifest. All of the references which are installed with the 2.0 framework are replaced with this one, because we take it on faith that if this one assembly is installed, all of the assemblies from that .NET Framework version are also installed. This one assembly has a special name: the "sentinel assembly". 
&lt;P&gt;When Visual Studio 2008 and its multi-targeting features came out, the sentinel assembly pattern was continued. When targeting the 3.0 Framework, the 3.0 assembly references are covered by the "WindowsBase" sentinel:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;dependencyType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;preRequisite&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;allowDelayedBinding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;assemblyIdentity&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;WindowsBase&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;3.0.0.0&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;publicKeyToken&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;31bf3856ad364e35&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;language&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;neutral&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;processorArchitecture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;msil&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;Targeting the 3.5 framework used the "System.Core" sentinel:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;dependencyType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;preRequisite&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;allowDelayedBinding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;assemblyIdentity&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;System.Core&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;3.5.0.0&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;publicKeyToken&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;b77a5c561934e089&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;language&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;neutral&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;processorArchitecture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;msil&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The GenerateApplicationManifest task figures out which sentinel assembly to write based on a project property: the TargetFrameworkVersion property, which has an expected value of 2.0, 3.0, or 3.5. It does not use project references; within the project system, it's this framework version property which dictates the references that can be added to the appliction.&lt;/P&gt;
&lt;P&gt;This brings us to Visual Studio 2008 SP1. When we first started planning for ClickOnce tooling for the service pack, it was obvious there would be the need for a new sentinel assembly. Once we heard the ginormous new set of features being added to the .NET Framework, we assumed there would be a whole new framework version. We were told there wouldn't be: the new feature set would be billed as a 3.5 "service pack", with the features being added into existing assemblies or entirely new assemblies.&lt;/P&gt;
&lt;P&gt;Well, surely there will be a new "TargetFrameworkVersion" property the project system so that the manifest generation knows which set of sentinel assemblies to write into the manifest. Afraid not: the team that owned that property didn't have time to add a new option.&lt;/P&gt;
&lt;P&gt;Okay, how about if we decide to always write out the 3.5 SP1 sentinel assembly? We were told that was fine: and there's even a good sentinel assembly to write out:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;dependencyType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;preRequisite&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;allowDelayedBinding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;assemblyIdentity&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;System.Data.Entity&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;3.5.0.0&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;publicKeyToken&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;b77a5c561934e089&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;language&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;neutral&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;processorArchitecture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;msil&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;dependentAssembly&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;With that sentinel assembly decision out of the way, we decided to focus on adding tooling support for the 3.5 features that we missed, and were being added to the 3.5 SP1. These features are: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;B&gt;File Associations&lt;/B&gt;: &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2008/01/30/how-to-add-file-associations-to-a-clickonce-application.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2008/01/30/how-to-add-file-associations-to-a-clickonce-application.aspx"&gt;I already wrote&lt;/A&gt; about this, but we added UI support for file associations.&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Exclude deployment provider&lt;/B&gt;: When this options is checked, manifest generation will NOT include the deploymentProvider tag when it would under "normal" circumstances. This was supported in the VS 2008 product, but there was no UI for it.&lt;/LI&gt;&lt;/UL&gt;We also added support for some (if not all) of the new ClickOnce features added for 3.5 SP1. Here's a rundown, including my commentary: 
&lt;UL&gt;
&lt;LI&gt;&lt;B&gt;Suite Name&lt;/B&gt;: Places the start menu shortcut into a sub-folder. I think the goal of this one was to create a means for grouping similar applications into the same start menu folder, like Microsoft Office.&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Error URL&lt;/B&gt;: Specifies the &lt;A class="" href="http://msdn.microsoft.com/en-us/library/cc679074.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc679074.aspx"&gt;web page&lt;/A&gt; a user will be sent to if the installation of an application fails. My 2 cents: while I understand the ClickOnce team's heart was in the right place, I think this feature could have been executed better. At the very least, I would have liked to have seen 2 additions to this feature: 
&lt;OL&gt;
&lt;LI&gt;A published web page template that would show reasonable help for some of the more common installation errors (something like the generated publish.htm, except about 1000 times more complicated)&lt;/LI&gt;
&lt;LI&gt;Including the application identity for the failed installation&lt;/LI&gt;&lt;/OL&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Create desktop shortcut&lt;/B&gt;: Adds a shortcut to the desktop for the application that is being installed. A lot of people like this, a lot of people don't (I fall into the latter). But its nice to have the option.&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Optional hashing&lt;/B&gt;: In the past, a file deployed with the application included a hash of the file when it was published. The hash was included for 2 reasons. Security: to make sure that the file that was published was consistent with the file that was downloaded. Updates: If ClickOnce is installing an update, downloading of a file would be skipped if the hash values for the old application and the new application were the same. Excluding a hash means that you can change a file post-publish. A potentially useful feature; I'm curious to hear if people modify files other than the .exe.config file.&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Optional Signing&lt;/B&gt;: In the past, ClickOnce manifests needed to be signed in order to install. That restriction has been removed. Note that if a hash has been excluded, the manifests can not be signed. Publishing still defaults to signing the manifests, but once an application has been published, it is possible to turn off this feature (yes, this means you have to publish twice. We are sorry).&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Of course, all of this required a new and improved publish options page: the old one was getting too crowded. The available properties were re-grouped into a format similar to what's in Tools: Options.&lt;/P&gt;
&lt;P&gt;While the next set of features weren't added by the ClickOnce tooling team, they do affect ClickOnce published applications:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;B&gt;.NET Framework Client Profile&lt;/B&gt;: Publishing your &lt;A class="" href="http://msdn.microsoft.com/en-us/library/cc656912.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc656912.aspx"&gt;Client Profile&lt;/A&gt; application adds additional information into the manifest to make sure that it can run on either the full 3.5 SP1 or the .NET Framework Client Profile. The profile includes all of the new 3.5 SP1 ClickOnce enhancements. I see how this profile might be a wonderful idea, but unfortunately additional tooling support is required to turn this into a nice experience.The good news: I'll probably get another blog post out of this.&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Additional Bootstrapper Packages&lt;/B&gt;: Bootstrapper packages have been added for the full 3.5 SP1, the client profile, Visual Basic Power Packs (1.2), and Visual Studio Tools for Office. The bootstrapper for SQL Server Express 2008 is available when you install VB or C# Express.&lt;/LI&gt;&lt;/UL&gt;Finally, some high-profile bug fixes were done: 
&lt;UL&gt;
&lt;LI&gt;&lt;B&gt;Publishing WPF applications&lt;/B&gt;: In VS 2008, &lt;A class="" href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=318702" target=_blank mce_href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=318702"&gt;strange errors&lt;/A&gt; may crop up when publishing a WPF application: "...g.i.cs file can not be found".&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;Update to publish.htm&lt;/B&gt;: The javascript detection that is in place for detecting .NET Framework 2.0 of your application has been expanded to include .NET 3.0 and 3.5 SP1&lt;/LI&gt;
&lt;LI&gt;&lt;B&gt;XML Serializer assemblies are now published with the application&lt;/B&gt;: I wrote a &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2008/06/30/how-to-include-xmlserializers-in-your-clickonce-application.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2008/06/30/how-to-include-xmlserializers-in-your-clickonce-application.aspx"&gt;blog post&lt;/A&gt; about this one, too. No need to use this work-around.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;After all of this work was done, the tooling team was told that it was no longer acceptable to target 3.5 SP1 by default. Instead, when pulishing the application, the manifest generation tasks should be smart about this and only include the 3.5 SP1 sentinel assembly when it is "necessary". Unfortunately, because of how the service pack is constructed it is very difficult for manifest generation to know whether or not 3.5 SP1 is necessary. At manifest generation time, the relevant tasks deal only with project references, files, and ClickOnce properties. Manifest generation has no idea what a user is doing with those references, it only know the names of the references. And because 3.5 SP1 features were added to existing (2.0, 3.0, and 3.5) Framework assemblies, it isn't possible to base the sentinel addition on the referenced assembly list. This is why the a &lt;A class="" href="http://msdn.microsoft.com/en-us/library/bb398202.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb398202.aspx"&gt;hack&lt;/A&gt; was settled upon: if your application requires 3.5 SP1, you should explicitly reference System.Data.Entity.dll. The manifest generation tool will understand what this means, and will add this sentinel assembly into the manifest file. Manifest generation will also (silently) add the 3.5 SP1 sentinel assembly if your application uses features only available in the 3.5 service pack.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8907039" width="1" height="1"&gt;</description></item><item><title>How To: Publish Output Groups from Other Projects in a ClickOnce Project</title><link>http://blogs.msdn.com/mwade/archive/2008/07/31/how-to-publish-output-groups-from-other-projects-in-a-clickonce-project.aspx</link><pubDate>Thu, 31 Jul 2008 23:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8794735</guid><dc:creator>mwade</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/mwade/comments/8794735.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=8794735</wfw:commentRss><description>&lt;P&gt;In addition to output from a "compile", projects are capable of creating other outputs. Setup projects can consume the output from other projects, package them up, and install them as part of the generated Windows Installer package. These groups of different outputs are referred to as, well, "output groups", and are exposed through the DTE as the following macro demonstrates:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;Sub&lt;/FONT&gt; ListAll() 
    &lt;FONT color=#0000ff&gt;For&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;Each&lt;/FONT&gt; proj &lt;FONT color=#0000ff&gt;As&lt;/FONT&gt; Project &lt;FONT color=#0000ff&gt;In&lt;/FONT&gt; DTE.Solution.Projects 
        &lt;FONT color=#0000ff&gt;Dim&lt;/FONT&gt; groupInfo &lt;FONT color=#0000ff&gt;As&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;New&lt;/FONT&gt; StringBuilder() 
        &lt;FONT color=#0000ff&gt;If&lt;/FONT&gt; proj.ConfigurationManager &lt;FONT color=#0000ff&gt;IsNot&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;Nothing&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;Then&lt;/FONT&gt; 
            &lt;FONT color=#0000ff&gt;For&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;Each&lt;/FONT&gt; group &lt;FONT color=#0000ff&gt;As&lt;/FONT&gt; OutputGroup &lt;FONT color=#0000ff&gt;In&lt;/FONT&gt; proj.ConfigurationManager.ActiveConfiguration.OutputGroups 
                groupInfo.AppendLine(&lt;FONT color=#0000ff&gt;String&lt;/FONT&gt;.Format(&lt;FONT color=#a31515&gt;"{0}: {1} ({2})"&lt;/FONT&gt;, group.CanonicalName, group.DisplayName, group.FileCount)) 
            &lt;FONT color=#0000ff&gt;Next&lt;/FONT&gt; 
            MsgBox(groupInfo.ToString(), MsgBoxStyle.OkOnly, proj.Name) 
        &lt;FONT color=#0000ff&gt;End&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;If&lt;/FONT&gt; 
    &lt;FONT color=#0000ff&gt;Next&lt;/FONT&gt; 
&lt;FONT color=#0000ff&gt;End&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;Sub&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The results for a very basic Winform Application is shown below:&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Project Output Groups" style="WIDTH: 249px; HEIGHT: 185px" height=185 alt="Project Output Groups" src="http://blogs.msdn.com/photos/mwade/images/8794750/original.aspx" width=249 mce_src="http://blogs.msdn.com/photos/mwade/images/8794750/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;It is a design &lt;STRIKE&gt;limitation&lt;/STRIKE&gt; decision that ClickOnce projects are capable of publishing all of these output groups from its own project, but if you want the content, source, symbols, or documentation files from a different project in the solution, you are just plain out of luck. However, if you are willing to modify your project file just a little bit, your luck has just changed. Let's build upon an entry from &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2008/06/29/how-to-publish-files-which-are-not-in-the-project.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2008/06/29/how-to-publish-files-which-are-not-in-the-project.aspx"&gt;last month&lt;/A&gt;&amp;nbsp;and have a ClickOnce project publish output from other projects. &lt;/P&gt;
&lt;P&gt;Its not well advertised, but there are Targets within Microsoft.Common.targets which expose the output groups of a project. For example, here is the Target which exposes the Content Files output group:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt; 
            &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ContentFilesProjectOutputGroup&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;Outputs&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(ContentFilesProjectOutputGroupOutput)&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;DependsOnTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ContentFilesProjectOutputGroupDependsOn)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;!--&lt;/FONT&gt; &lt;FONT color=#008000&gt;Convert items into final items; this way we can get the full path for each item.&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;--&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ContentFilesProjectOutputGroupOutput&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(ContentWithTargetPath-&amp;gt;'%(FullPath)')&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;It would be tempting to simply add this Target as a dependency to the BeforePublish target used in the project file. However, doing so would get the contents of &lt;B&gt;this&lt;/B&gt; project, not some other project. What we really need is to run MSBuild on a different project, call this target, and consume that target's outputs. And MSBuild has a way to do exactly that: The &lt;A class="" href="http://msdn.microsoft.com/en-us/library/z7f65y0d.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/z7f65y0d.aspx"&gt;MSBuild task&lt;/A&gt;.&lt;/P&gt;By using the MSBuild task, it is possible to modify the BeforePublish target to consume the outputs of another project. Something like this should do the trick: &lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishPOG&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;..\\ClassLibrary1\\ClassLibrary1.vbproj&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;false&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;OutputGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;DebugSymbolsProjectOutputGroup&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;OutputGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishPOG&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishPOG&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;..\\ClassLibrary2\\ClassLibrary2.vbproj&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;false&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;OutputGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;ContentFilesProjectOutputGroup&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;OutputGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishPOG&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;BeforePublish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Touch&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Files&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(IntermediateAssembly)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;MSBuild&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Projects&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;%(PublishPOG.Identity)&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;Targets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;%(OutputGroup)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;TargetOutputs&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_DeploymentManifestFiles&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;MSBuild&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;This change consumes the outputs of two different projects: the debug symbols from ClassLibrary1 and the content files from ClassLibrary2 (why anyone would want to publish the pdbs of another project is left as an exercise to the reader). This information is stored as an item with identity of the project to build and the output group to consume. BeforePublish then calls the MSBuild task to append the outputs onto the _DeploymentManifestFiles item, which is consumed by the GenerateApplicationManifest task (amongst others). So, which outputs are available for consumption? Here is a handy chart for reference:&lt;/P&gt;
&lt;CENTER&gt;
&lt;TABLE class="" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;B&gt;Output Type&lt;/B&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;B&gt;MSBuild Target Name&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Content Files&lt;/TD&gt;
&lt;TD class=""&gt;ContentFilesProjectOutputGroup&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Source Files&lt;/TD&gt;
&lt;TD class=""&gt;SourceFilesProjectOutputGroup&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Debug Symbols&lt;/TD&gt;
&lt;TD class=""&gt;DebugSymbolsProjectOutputGroup&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Documentation Files&lt;/TD&gt;
&lt;TD class=""&gt;DocumentationProjectOutputGroup&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Localized resources&lt;/TD&gt;
&lt;TD class=""&gt;SatelliteDllsProjectOutputGroup&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Serialization assemblies&lt;/TD&gt;
&lt;TD class=""&gt;SGenFilesOutputGroup&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Primary output&lt;/TD&gt;
&lt;TD class=""&gt;BuiltProjectOutputGroup&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/CENTER&gt;
&lt;P&gt;Note that the satellite dlls, serialization assemblies, and primary output of another project are generally included simply by adding a reference to that other project. But if you do go down this route for these output types, you should append the output to the &lt;CODE&gt;_DeploymentManifestDependencies&lt;/CODE&gt; item instead of &lt;CODE&gt;_DeploymentManifestFiles&lt;/CODE&gt;.&lt;/P&gt;
&lt;P&gt;All of this talk of "output groups" and "ClickOnce" naturally (I think) leads to another question. I don't want to ask it because I don't want to answer it (right now). But if someone wants to ask, feel free to leave a comment. Its a question I want to answer with a later post, but we'll see if it happens.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8794735" width="1" height="1"&gt;</description></item><item><title>How To: Include XmlSerializers in your ClickOnce Application</title><link>http://blogs.msdn.com/mwade/archive/2008/06/30/how-to-include-xmlserializers-in-your-clickonce-application.aspx</link><pubDate>Tue, 01 Jul 2008 08:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8675290</guid><dc:creator>mwade</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/mwade/comments/8675290.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=8675290</wfw:commentRss><description>&lt;P&gt;Have you ever noticed that when your application has a web reference, and you go to publish that web reference, the expected XmlSerializers assembly is not written into the application manifest, nor is it deployed with the application? You haven't? Not too many people have: it rarely comes up in the forums I scan, but we have received a couple of support calls about this. The answers I have given in the past include things like:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Expose the web service methods through a partner Class Library, and take a reference on that Class Library&lt;/LI&gt;
&lt;LI&gt;Make some modifications to Microsoft.Common.targets&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;In fact there is an easier way, which is similar to my &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2008/06/29/how-to-publish-files-which-are-not-in-the-project.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2008/06/29/how-to-publish-files-which-are-not-in-the-project.aspx"&gt;last blog post&lt;/A&gt;. By adding the following information to your project file, the XmlSerializers assembly will start getting published with your application:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;BeforePublish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;CreateItem&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;%(SerializationAssembly.FullPath)&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;'%(Extension)' == '.dll'&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Include&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_SGenDllsRelatedToCurrentDll&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;Once again, &lt;CODE&gt;BeforePublish&lt;/CODE&gt; is pre-populating some items to include some information for the ClickOnce manifest generation. In this case, the &lt;CODE&gt;_SGenDllsRelatedToCurrentDll&lt;/CODE&gt; items are used by the &lt;CODE&gt;ResolveManifestFiles&lt;/CODE&gt; task to figure out what should be published. The definition of &lt;CODE&gt;SGenDllsRelatedToCurrentDll&lt;/CODE&gt; in Microsoft.Common.targets only picks up on SGen Dlls from referenced projects, but misses the XmlSerializers from the exe project (which is why the first work-around mentioned above will work). Making this change allows the XmlSerializers to be picked up, and you can even set properties on them in the Application Files dialog. &lt;/P&gt;
&lt;P&gt;Note: This problem existed in both VS 2005 and VS 2008. This work-around doesn't work for VS 2005 (so far, I haven't been able to come up with something that didn't require modifying Microsoft.Common.targets (or re-defining &lt;CODE&gt;GenerateApplicationManifest&lt;/CODE&gt; target)). Furthermore, this issue is fixed in VS 2008 SP1 (to be precise: it is fixed in .NET Framework 3.5 SP1). The fix taken in there is basically what I showed here: Including the &lt;CODE&gt;SerializationAssembly&lt;/CODE&gt; in the &lt;CODE&gt;_SGenDllsRelatedToCurrentDll&lt;/CODE&gt; items.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8675290" width="1" height="1"&gt;</description></item><item><title>How To: Publish Files Which are not in the Project</title><link>http://blogs.msdn.com/mwade/archive/2008/06/29/how-to-publish-files-which-are-not-in-the-project.aspx</link><pubDate>Mon, 30 Jun 2008 06:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8669881</guid><dc:creator>mwade</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/mwade/comments/8669881.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=8669881</wfw:commentRss><description>&lt;P&gt;Every one in a while on our ClickOnce forums, we are asked how to publish files that aren't part of the project. The short answer is: you can't. The ClickOnce project is only capable of publishing files (build output, data, or content files) which are part of the project (or referenced by the project). If you have a file in a different project that you want to add to your publishing project, you can't simply add that item to your ClickOnce project: the project system will copy the file to the ClickOnce project directory. This means that any change you make to the file in the original project will be lost in the ClickOnce project, unless you remember to make the corresponding change in your ClickOnce project. It's possible to better manage this mess by adding the item &lt;A class="" href="http://msdn.microsoft.com/en-us/library/9f4t9t92.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/9f4t9t92.aspx"&gt;as a link&lt;/A&gt;; that helps a little, but you still have to add all of the files you want to publish into the project.&lt;/P&gt;
&lt;P&gt;This wouldn't be an issue if the ClickOnce project were able to deal with Project Output Groups like a &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aw8sakc1.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/aw8sakc1.aspx"&gt;setup project can&lt;/A&gt;. Hopefully I will get to that in a later post, but for now let's keep it a little more simple: is there some way to include all of the files in a given directory in the ClickOnce publish? This is, after all, how mage operates. The answer is "yes", if you are willing to make some by-hand modifications to a project file. I won't be dealing with assemblies in this post; the need to do so isn't as pressing: I think it's more rare for an application to require a lot of assemblies as references that aren't adequately addressed with the current system for dealing with references. Indeed, you can think of project-to-project references as similar to project output groups, and other references match the "link" analogy, as references are not copied locally and then dealt with statically by the project system. Instead, I want to focus on how those assemblies which may require their own content files can make sure those are deployed with the ClickOnce application.&lt;/P&gt;
&lt;P&gt;Let's get started by exploring how information from the application files dialog makes the journey to what gets written into the application manifest. For those of you who want to play along at home, I created a solution containing a Windows Forms Application and 2 class library projects. I also added 5 text files to a sub-folder of the WinForms project, one of which was added as a link. I changed a bunch of settings in the application files dialog, like this:&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Application Files Dialog" style="WIDTH: 600px; HEIGHT: 440px" height=440 alt="Application Files Dialog" src="http://blogs.msdn.com/photos/mwade/images/8669899/original.aspx" width=600 mce_src="http://blogs.msdn.com/photos/mwade/images/8669899/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;Viewing the contents of the project file, we see this:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ClassLibrary1&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Include&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Assembly&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ClassLibrary2&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Prerequisite&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Assembly&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;NewFolder1\\TextFile2.txt&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Foo&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Auto&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;File&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;NewFolder1\\TextFile3.txt&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Exclude&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;File&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;NewFolder1\\TextFile4.txt&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Foo&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;DataFile&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;File&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;NewFolder1\\TextFileLink.txt&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Group&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Include&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishState&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;TargetPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;File&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;FileType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;PublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;All sorts of observations can be made:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Application File items are stored as Items with name "&lt;CODE&gt;PublishFile&lt;/CODE&gt;"&lt;/LI&gt;
&lt;LI&gt;The &lt;CODE&gt;Include&lt;/CODE&gt; value is the name of the file in the application files dialog&lt;/LI&gt;
&lt;LI&gt;If a metadata value is in the default state, it is generally left blank&lt;/LI&gt;
&lt;LI&gt;If the entire item is in a default state, there is no entry for it in the project file (see TextFile1.txt for example)&lt;/LI&gt;
&lt;LI&gt;There are 5 different metadata values for the &lt;CODE&gt;PublishFile&lt;/CODE&gt; item&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;CODE&gt;Visible&lt;/CODE&gt;, which determines whether or not the Item appears in the solution explorer (always "False" because all of these have different representations within the project file)&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Group&lt;/CODE&gt;, which corresponds to the Download Group in the application files dialog&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;PublishState&lt;/CODE&gt;, which corresponds to how the file is distributed. There appear to be 5 different values&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;(Auto)&lt;/CODE&gt;: The file is in its default state&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Include&lt;/CODE&gt;: The file will be published with the project&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Exclude&lt;/CODE&gt;: The file will NOT be published with the project&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;DataFile&lt;/CODE&gt;: The file will be published as a data file&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Prerequisite&lt;/CODE&gt;: The assembly will not be published with the application, but will be written into the manifest as a prerequisite&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;CODE&gt;TargetPath&lt;/CODE&gt;, which corresponds to the location relative to the application manifest the file will be published to (this is value is not settable through the application files dialog)&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;FileType&lt;/CODE&gt;, which describes what kind of file this is&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;Assembly&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;File&lt;/CODE&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/OL&gt;&lt;/UL&gt;
&lt;P&gt;Now that we have some idea of how files are included in output, let's see how they are applied by MSBuild. To do that, we start by opening Microsoft.Common.targets. Performing a search for &lt;CODE&gt;@(PublishFile)&lt;/CODE&gt;, we see the following entry:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;!--&lt;/FONT&gt; &lt;FONT color=#008000&gt;Create list of items for manifest generation&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;--&amp;gt; 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ResolveManifestFiles&lt;/FONT&gt; 
                &lt;FONT color=#ff0000&gt;EntryPoint&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(_DeploymentManifestEntryPoint)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;ExtraFiles&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(_DebugSymbolsIntermediatePath);$(IntermediateOutputPath)$(TargetName).xml;@(_ReferenceRelatedPaths)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;Files&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(ContentWithTargetPath);@(_DeploymentManifestIconFile);@(AppConfigWithTargetPath)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;ManagedAssemblies&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(_DeploymentReferencePaths);@(ReferenceDependencyPaths);@(_SGenDllsRelatedToCurrentDll)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;NativeAssemblies&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(NativeReferenceFile);@(_DeploymentNativePrerequisite)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;PublishFiles&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(PublishFile)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;SatelliteAssemblies&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(IntermediateSatelliteAssembliesWithTargetPath);@(ReferenceSatellitePaths)&lt;/FONT&gt;" 
                &lt;FONT color=#ff0000&gt;TargetCulture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(TargetCulture)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;OutputAssemblies&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_DeploymentManifestDependencies&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;OutputFiles&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_DeploymentManifestFiles&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;/&amp;gt; 
 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ResolveManifestFiles&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;This &lt;CODE&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/microsoft.build.tasks.resolvemanifestfiles.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/microsoft.build.tasks.resolvemanifestfiles.aspx"&gt;ResolveManifestFiles&lt;/A&gt;&lt;/CODE&gt; task takes all sorts of information (including &lt;CODE&gt;PublishFile&lt;/CODE&gt; items). It returns the &lt;CODE&gt;OutputAssemblies&lt;/CODE&gt; and &lt;CODE&gt;OutputFiles&lt;/CODE&gt; as &lt;CODE&gt;_DeploymentManifestDependencies&lt;/CODE&gt; and &lt;CODE&gt;_DeploymentManifestFiles&lt;/CODE&gt; items, respectively. These items are then used by the &lt;CODE&gt;GenerateApplicationManifest&lt;/CODE&gt; and a pair of &lt;CODE&gt;Copy&lt;/CODE&gt; tasks within the &lt;CODE&gt;_CopyFilesToPublishFolder&lt;/CODE&gt; target. Before we latch onto these values to publish files not in the project, let's see what sort of metadata the items carry along.&lt;/P&gt;
&lt;P&gt;You could write your own task to figure this out, or you could take my word for it: here is the relevant metadata names for &lt;CODE&gt;_DeploymentManifestFiles&lt;/CODE&gt;:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;Group&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;TargetPath&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;IsDataFile&lt;/CODE&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;It's a similar group to what was written for &lt;CODE&gt;PublishFile&lt;/CODE&gt; items. It appears that (for files) &lt;CODE&gt;PublishState&lt;/CODE&gt; was used mapped to &lt;CODE&gt;IsDataFile&lt;/CODE&gt; by the &lt;CODE&gt;ResolveManifestFiles&lt;/CODE&gt; task. The &lt;CODE&gt;FileType&lt;/CODE&gt; metadata was used used to break all &lt;CODE&gt;PublishFile&lt;/CODE&gt; items into the assemblies and files group.&lt;/P&gt;
&lt;P&gt;Let's check out the metadata values from these names. Let's modify the winform project file to display all of this metadata. Unload the project within Visual Studio and edit it with the following info:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;AfterPublish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Message&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_DeploymentManifestFiles (Identity=%(_DeploymentManifestFiles.Identity))&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;
&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;\tab Group=%(_DeploymentManifestFiles.Group)&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;
&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;\tab TargetPath=%(_DeploymentManifestFiles.TargetPath)&lt;/FONT&gt;&lt;FONT color=#ff0000&gt;
&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;\tab IsDataFile=%(_DeploymentManifestFiles.IsDataFile)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;After publishing, the output window shows (amongst other things):&lt;/P&gt;&lt;PRE&gt;_DeploymentManifestFiles (Identity=..\..\..\..\TextFileLink.txt)
    	Group=
    	TargetPath=NewFolder1\TextFileLink.txt
    	IsDataFile=false
_DeploymentManifestFiles (Identity=NewFolder1\TextFile1.txt)
    	Group=
    	TargetPath=NewFolder1\TextFile1.txt
    	IsDataFile=false
_DeploymentManifestFiles (Identity=NewFolder1\TextFile2.txt)
   	Group=Foo
    	TargetPath=NewFolder1\TextFile2.txt
    	IsDataFile=false
_DeploymentManifestFiles (Identity=NewFolder1\TextFile4.txt)
    	Group=
    	TargetPath=NewFolder1\TextFile4.txt
    	IsDataFile=true
&lt;/PRE&gt;
&lt;P&gt;So to add additional files to our output, we need only figure out how to generate new &lt;CODE&gt;_DeploymentManifestFiles&lt;/CODE&gt; items. It turns out this is easy enough. Consider the following piece of information written into the project file:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;AdditionalPublishFile&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;C:\\Documents and Settings\\mwade\\My Documents\\My Pictures\\*.jpg&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;AdditionalPublishFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;BeforePublish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Touch&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Files&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(IntermediateAssembly)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;CreateItem&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(AdditionalPublishFile)&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;AdditionalMetadata&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;TargetPath=%(FileName)%(Extension);IsDataFile=false&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Include&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_DeploymentManifestFiles&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;These statements take all of the jpg files in my My Pictures directory, stores each item in a &lt;CODE&gt;AdditionalPublishFile&lt;/CODE&gt;. Then as part of &lt;CODE&gt;BeforePublish&lt;/CODE&gt; target, the &lt;CODE&gt;PublishDirectoryFile&lt;/CODE&gt; are used (via the &lt;CODE&gt;CreateItem&lt;/CODE&gt; task) to pre-populate the &lt;CODE&gt;_DeploymentManifestFiles&lt;/CODE&gt; items. The &lt;CODE&gt;CreateItem&lt;/CODE&gt; task sets the necessary metadata for &lt;CODE&gt;_DeploymentManifestFiles&lt;/CODE&gt;: &lt;CODE&gt;TargetPath&lt;/CODE&gt;, &lt;CODE&gt;Group&lt;/CODE&gt;, and &lt;CODE&gt;IsDataFile&lt;/CODE&gt;. The &lt;CODE&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/37fwbyt5.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/37fwbyt5.aspx"&gt;Touch&lt;/A&gt;&lt;/CODE&gt; task is used to make sure that &lt;CODE&gt;GenerateApplicationManifest&lt;/CODE&gt; task is re-run as part of the publish process. &lt;CODE&gt;Touch&lt;/CODE&gt; modifies the write time of the primary executable. This file is an input to the &lt;CODE&gt;GenerateApplicationManifest&lt;/CODE&gt; task, and with a write time later than the write time of the application manifest (the task output), MSBuild will not skip the task. Publishing the project shows that these files are indeed written into the application manifest. Furthermore, the publishing service makes sure these files are published to the remote server. You can use your own MSBuild magic to include which ever files you want to include.&lt;/P&gt;
&lt;P&gt;One thing to note: I have only tested this on VS 2008, and I don't know how well things will work on Visual Studio 2005. My expectation is that the manifest generation should be basically the same; however, its possible the files will not be automatically published with the application.&lt;/P&gt;
&lt;P&gt;One final note: strictly speaking, MSBuild guidelines indicate that things which begin with "_" are supposed to indicate that the things are not for public consumption. So, we could take the approach of re-defining the Publish tasks to enable this scenario (and we could get that to work), but that would involve re-defining targets which are also considered "private" because they start with "_" as well. So either way, we're doing something we shouldn't; taking this approach will definitely be the easiest route.&lt;/P&gt;&lt;I&gt;Update 7/2/2008: Added information regarding the &lt;CODE&gt;Touch&lt;/CODE&gt; task.&lt;/I&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8669881" width="1" height="1"&gt;</description></item><item><title>How To: Use Macros to Configure Publish Settings</title><link>http://blogs.msdn.com/mwade/archive/2008/05/31/how-to-use-macros-to-configure-publish-settings.aspx</link><pubDate>Sun, 01 Jun 2008 04:06:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8567233</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/8567233.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=8567233</wfw:commentRss><description>&lt;p&gt;There are all sorts of publishing properties available to the Visual Studio developer. Visual Studio tries to set the properties to reasonable default values. But with all things that are defaulted, the values are right for some people, but wrong for others. In my day-to-day work, where I run through publishing quite a bit, there are quite a few values I want to reset. Its possible to click through the UI to change the values, but who has a couple of seconds to spare to open dialogs and click on stuff? Not I; every second lost is a second I could spend writing a blog entry. Fortunately, its easy to create a macro that will set these values for you. In this post, I'll write about you can use a macro to set these default values through the DTE.&lt;/p&gt;  &lt;h3&gt;Displaying publish properties and values&lt;/h3&gt;  &lt;p&gt;Let's start by viewing all available publishing properties. Before going too far, let's show some helper functions to accomplish our tasks. Here is some code I copied from my macro explorer:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; GetPublishProperties() &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; proj &lt;span class="kwrd"&gt;As&lt;/span&gt; Project = DTE.Solution.Projects.Item(1)
    &lt;span class="kwrd"&gt;If&lt;/span&gt; proj &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        ShowError(&lt;span class="str"&gt;&amp;quot;Unable to retrieve a project&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;GetPublishProperties&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperty &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.&lt;span class="kwrd"&gt;Property&lt;/span&gt; = proj.Properties.Item(&lt;span class="str"&gt;&amp;quot;Publish&amp;quot;&lt;/span&gt;)
    &lt;span class="kwrd"&gt;If&lt;/span&gt; publishProperty IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = &lt;span class="kwrd"&gt;TryCast&lt;/span&gt;(publishProperty.Value, EnvDTE.Properties)
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; publishProperties
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    ShowError(&lt;span class="str"&gt;&amp;quot;Unable to get publish properties of project &amp;quot;&lt;/span&gt; &amp;amp; proj.Name, &lt;span class="str"&gt;&amp;quot;GetPublishProperties&amp;quot;&lt;/span&gt;)
    &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;

&lt;span class="kwrd"&gt;Sub&lt;/span&gt; ShowError(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; message &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; title &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;)
    MsgBox(message, MsgBoxStyle.Exclamation &lt;span class="kwrd"&gt;Or&lt;/span&gt; MsgBoxStyle.OkOnly, title)
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

&lt;span class="kwrd"&gt;Sub&lt;/span&gt; ShowException(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; methodName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;)
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; message &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = ex.Message
    &lt;span class="kwrd"&gt;If&lt;/span&gt; ex.InnerException IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        message = ex.InnerException.Message
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
    ShowError(message, methodName)
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&lt;code&gt;GetPublishProperties&lt;/code&gt; is a function to retrieve the object which contains the publish properties. It grabs the first project in the solution, and selects the &amp;quot;Publish&amp;quot; property from there. Next, the resultant property value is converted to another properties container. Some error handling is also included (although probably not enough).&lt;/p&gt;

&lt;p&gt;With that as a baseline, this macro will show all of the publish properties, types, and values:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; ShowPublishProperties()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = GetPublishProperties()
    &lt;span class="kwrd"&gt;If&lt;/span&gt; publishProperties IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; sb &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Text.StringBuilder()
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; prop &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.&lt;span class="kwrd"&gt;Property&lt;/span&gt; &lt;span class="kwrd"&gt;In&lt;/span&gt; publishProperties
            sb.Append(&lt;span class="kwrd"&gt;String&lt;/span&gt;.Format(&lt;span class="str"&gt;&amp;quot;{0} [{1}]: {2}&amp;quot;&lt;/span&gt;, prop.Name, prop.Value.&lt;span class="kwrd"&gt;GetType&lt;/span&gt;().ToString(), prop.Value.ToString()))
            sb.Append(vbCrLf)
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        MsgBox(sb.ToString())
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;This macro simply iterates through all of the publish properties, gathers the property names, types, and values and show them all in a message box. Here is a subset of the output:&lt;/p&gt;

&lt;pre&gt;PublisherName [System.String]: 
OpenBrowserOnPublish [System.Boolean]: True
BootstrapperComponentsLocation [System.Int32]: 0
PublishFiles [System.__ComObject]: System.__ComObject&lt;/pre&gt;

&lt;p&gt;Most of the values are &lt;code&gt;strings&lt;/code&gt;, &lt;code&gt;ints&lt;/code&gt;, or &lt;code&gt;booleans&lt;/code&gt;. If you were to look in the project file, you would see that these values correspond to properties within the file. The exception are &lt;code&gt;PublishFiles&lt;/code&gt; and &lt;code&gt;BootstrapperPackages&lt;/code&gt;, which correspond to the Items in the project file, as well as the the lists within the Application Files dialog and Prerequisites dialog. These will be explored further in a bit. But first, let's try setting some easy values.&lt;/code&gt; &lt;/p&gt;

&lt;h3&gt;Setting Property values&lt;/h3&gt;

&lt;p&gt;Setting a value is as easy as reading a value. For example, to set the &lt;code&gt;PublisherName&lt;/code&gt; property, one could write a macro like this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; SetPublisherName()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = GetPublishProperties()
    &lt;span class="kwrd"&gt;If&lt;/span&gt; publishProperties IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publisherNameProperty &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.&lt;span class="kwrd"&gt;Property&lt;/span&gt; = publishProperties.Item(&lt;span class="str"&gt;&amp;quot;PublisherName&amp;quot;&lt;/span&gt;)
        publisherNameProperty.Value = &lt;span class="str"&gt;&amp;quot;Test Value&amp;quot;&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Some properties perform validation when the values are set. For example, the &lt;code&gt;PublishUrl&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; SetPublishUrl()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = GetPublishProperties()
    &lt;span class="kwrd"&gt;If&lt;/span&gt; publishProperties IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Try&lt;/span&gt;
            publishProperties.Item(&lt;span class="str"&gt;&amp;quot;PublishUrl&amp;quot;&lt;/span&gt;).Value = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception
            ShowException(ex, &lt;span class="str"&gt;&amp;quot;SetPublishUrl&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;In the above example, an attempt is made to blank out the &lt;code&gt;PublishUrl&lt;/code&gt; property. However, the &lt;code&gt;PublishUrl&lt;/code&gt; can not be set to an empty string, as the thrown exception indicates:&lt;/p&gt;

&lt;pre&gt;An empty string is not allowed for property 'Publish Location'.&lt;/pre&gt;

&lt;p&gt;The thrown message uses &amp;quot;Publish Location&amp;quot; because that is what the label for the text box which corresponds to this property uses. In fact, the property page is pretty much setting this property in the exact same manner as the macro.&lt;/p&gt;

&lt;h3&gt;Modifying Items&lt;/h3&gt;

&lt;p&gt;There are 2 different types of &lt;code&gt;Items&lt;/code&gt; exposed by the Publish&lt;/p&gt;
Properties: &lt;code&gt;PublishFiles&lt;/code&gt; and &lt;code&gt;BootstrapperPackages&lt;/code&gt;. Here is a macro that does something with &lt;code&gt;PublishFiles&lt;/code&gt;:&lt;/code&gt; 

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; ListFiles()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = GetPublishProperties()
    &lt;span class="kwrd"&gt;If&lt;/span&gt; publishProperties IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; filesObject &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt; = publishProperties.Item(&lt;span class="str"&gt;&amp;quot;PublishFiles&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;If&lt;/span&gt; filesObject &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
             ShowError(&lt;span class="str"&gt;&amp;quot;Could not get PublishFiles object&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;ListFiles&amp;quot;&lt;/span&gt;)
            &lt;span class="kwrd"&gt;Return&lt;/span&gt;
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="kwrd"&gt;Try&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; numFiles &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
            numFiles = filesObject.Value.Item(&lt;span class="str"&gt;&amp;quot;Count&amp;quot;&lt;/span&gt;).Value
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; sb &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Text.StringBuilder()
            &lt;span class="kwrd"&gt;For&lt;/span&gt; i = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; numFiles - 1
                &lt;span class="rem"&gt;'display file name and publish status.&lt;/span&gt;
                sb.AppendLine(&lt;span class="str"&gt;&amp;quot;File Name=&amp;quot;&lt;/span&gt; &amp;amp; filesObject.&lt;span class="kwrd"&gt;Object&lt;/span&gt;.Item(i).Name &amp;amp; &lt;span class="str"&gt;&amp;quot;, Status=&amp;quot;&lt;/span&gt; &amp;amp; filesObject.&lt;span class="kwrd"&gt;Object&lt;/span&gt;.Item(i).PublishStatus)
            &lt;span class="kwrd"&gt;Next&lt;/span&gt;
            MsgBox(sb.ToString(), MsgBoxStyle.DefaultButton1, &lt;span class="str"&gt;&amp;quot;Application Files&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception
            ShowException(ex, &lt;span class="str"&gt;&amp;quot;ListFiles&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;This macro relies on latebinding in doing its work: &lt;code&gt;filesObject&lt;/code&gt; is declared as Object, yet it uses properties from that object. The &lt;code&gt;filesObject.Object&lt;/code&gt; contains an accessor to a collection; there are actually 2 ways to get a value out of the collection: one could use either a string to get a file by name, or an index, like what was done above. Here is some sample output from running this macro:&lt;/p&gt;

&lt;pre&gt;File Name=WindowsApplication2.exe, Status=0 
File Name=WindowsApplication2.pdb, Status=0 
File Name=WindowsApplication2.xml, Status=0 &lt;/pre&gt;

&lt;p&gt;The &amp;quot;Status&amp;quot; of the file corresponds to the Publish Status column in the Application Files dialog. 0 corresponds to the &amp;quot;(Auto)&amp;quot; value.&lt;/p&gt;

&lt;p&gt;Accessing the bootstrapper packages is similar:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; IncludeAllPrerequisites()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = GetPublishProperties()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bootstrapperPackages &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt; = publishProperties.Item(&lt;span class="str"&gt;&amp;quot;BootstrapperPackages&amp;quot;&lt;/span&gt;)
    &lt;span class="kwrd"&gt;If&lt;/span&gt; bootstrapperPackages IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; numPackages &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = bootstrapperPackages.Value.Item(&lt;span class="str"&gt;&amp;quot;Count&amp;quot;&lt;/span&gt;).Value
        &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; numPackages - 1
            bootstrapperPackages.&lt;span class="kwrd"&gt;Object&lt;/span&gt;.Item(i).Install = &lt;span class="kwrd"&gt;True&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

&lt;span class="kwrd"&gt;Sub&lt;/span&gt; ExcludeWindowsInstaller31()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; publishProperties &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE.Properties = GetPublishProperties()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bootstrapperPackages &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt; = publishProperties.Item(&lt;span class="str"&gt;&amp;quot;BootstrapperPackages&amp;quot;&lt;/span&gt;)
    &lt;span class="kwrd"&gt;If&lt;/span&gt; bootstrapperPackages IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; windowsInstaller31Package &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt; = bootstrapperPackages.&lt;span class="kwrd"&gt;Object&lt;/span&gt;.Item(&lt;span class="str"&gt;&amp;quot;Microsoft.Windows.Installer.3.1&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;If&lt;/span&gt; windowsInstaller31Package IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            windowsInstaller31Package.Install = &lt;span class="kwrd"&gt;False&lt;/span&gt;
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;The first macro includes all available prerequisites when publishing. In the first example, the packages are accessed by index. The second example gets a bootstrapper package by using a specific product code. 

&lt;h3&gt;Publishing via a macro&lt;/h3&gt;

&lt;p&gt;Finally, just like it is possible to build from a macro, it is possible to publish as well. Here is an example that does something similar to what the Publish Now button does on the Publish property page:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; Publish()
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; proj &lt;span class="kwrd"&gt;As&lt;/span&gt; Project = DTE.Solution.Projects.Item(1)
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; sb2 &lt;span class="kwrd"&gt;As&lt;/span&gt; EnvDTE80.SolutionBuild2 = &lt;span class="kwrd"&gt;CType&lt;/span&gt;(DTE.Solution.SolutionBuild, EnvDTE80.SolutionBuild2)
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; config2 = &lt;span class="kwrd"&gt;CType&lt;/span&gt;(sb2.ActiveConfiguration, EnvDTE80.SolutionConfiguration2)
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; configName = &lt;span class="kwrd"&gt;String&lt;/span&gt;.Format(&lt;span class="str"&gt;&amp;quot;{0}|{1}&amp;quot;&lt;/span&gt;, config2.Name, config2.PlatformName)
    sb2.BuildProject(configName, proj.UniqueName, &lt;span class="kwrd"&gt;True&lt;/span&gt;)
    sb2.PublishProject(configName, proj.UniqueName, &lt;span class="kwrd"&gt;True&lt;/span&gt;)
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;Ideally, the macro should verify that the build succeeded before publishing, but that has been left as an exercise for the reader. &lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8567233" width="1" height="1"&gt;</description></item><item><title>Tool: Editing File Associations for ClickOnce Applications</title><link>http://blogs.msdn.com/mwade/archive/2008/05/30/tool-editing-file-associations-for-clickonce-applications.aspx</link><pubDate>Fri, 30 May 2008 22:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8564184</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/8564184.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=8564184</wfw:commentRss><description>&lt;P&gt;I apologize for taking so long between posts. I have an excuse: very busy working on &lt;A class="" href="http://blogs.msdn.com/somasegar/archive/2008/05/12/visual-studio-2008-and-net-fx-3-5-sp1-beta-available-now.aspx" target=_blank mce_href="http://blogs.msdn.com/somasegar/archive/2008/05/12/visual-studio-2008-and-net-fx-3-5-sp1-beta-available-now.aspx"&gt;Visual Studio 2008 SP1 (Beta)&lt;/A&gt;. For those of you who have &lt;A class="" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CF99C752-1391-4BC3-BABC-86BC0B9E8E5A&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CF99C752-1391-4BC3-BABC-86BC0B9E8E5A&amp;amp;displaylang=en"&gt;downloaded the beta&lt;/A&gt;, this post won't do you much good, as the ability to set file associations for ClickOnce applications is already built in there. But for the rest of you, I've built a Visual Studio package based on upon a prototype I worked on for the Beta.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;About the package&lt;/STRONG&gt;: The package exposes an editor to work with file associations in the app.manifest file, as I wrote about in an &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2008/01/30/how-to-add-file-associations-to-a-clickonce-application.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2008/01/30/how-to-add-file-associations-to-a-clickonce-application.aspx"&gt;earlier post&lt;/A&gt;. The editor tries to provide some error and warning feedback to cover the cases I mentioned in that post.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Installing the package&lt;/STRONG&gt;: A link is provided at the bottom of the post to install the package.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Launching the editor&lt;/STRONG&gt;: To bring up the editor, bring up the context menu of a ClickOnce publishable project, and select "Edit File Associations...". The menu item should only be available for ClickOnce applications. The menu item is disabled for other project flavors; I couldn't figure out how to make a menuitem invisible (one would think setting the .Visible property to false would do it, but you would be sadly mistaken).&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Launching the editor" style="WIDTH: 304px; HEIGHT: 313px" height=313 alt="Launching the editor" src="http://blogs.msdn.com/photos/mwade/images/8564185/original.aspx" width=304 align=middle mce_src="http://blogs.msdn.com/photos/mwade/images/8564185/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;STRONG&gt;About the Editor&lt;/STRONG&gt;: Here's a screen shot of the editor. I'll go into the pieces below.&lt;/P&gt;
&lt;P&gt;&lt;IMG title="File Associations Editor" style="WIDTH: 634px; HEIGHT: 314px" height=314 alt="File Associations Editor" src="http://blogs.msdn.com/photos/mwade/images/8564194/original.aspx" width=634 mce_src="http://blogs.msdn.com/photos/mwade/images/8564194/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;Grid&lt;/EM&gt;: Sets the 4 values required for file associations. Editing is done in-place, but new items must be added via the New button. Errors and tool tips appear when an invalid value is set in the grid.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;New button&lt;/EM&gt;: Adds a new row to the grid, with some default values.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;Delete button&lt;/EM&gt;: Deletes a row from the grid.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;Warning&lt;/EM&gt;: Appears if some project properties would prevent the installation of the file associations from being valid.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Feedback/Updates&lt;/STRONG&gt;: I imagine there are a few problems with the package. If you have issues, please add a comment, and I'll try to update when I can.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8564184" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/8564184.ashx" length="358912" type="application/octet-stream" /></item><item><title>How To: Add File Associations to a ClickOnce Application</title><link>http://blogs.msdn.com/mwade/archive/2008/01/30/how-to-add-file-associations-to-a-clickonce-application.aspx</link><pubDate>Wed, 30 Jan 2008 23:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7333509</guid><dc:creator>mwade</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/mwade/comments/7333509.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=7333509</wfw:commentRss><description>&lt;P&gt;A little-known feature that made it into .NET Framework 3.5 is the ability for a ClickOnce application to be associated with document extensions. That is, once properly configured, double-clicking on a document can cause your ClickOnce application to launch. Right now, there is no direct tooling support for this feature (and if you ask me the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb882599.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/bb882599.aspx"&gt;MSDN information&lt;/A&gt; doesn't tell the whole story), but in this post I'll show you how you can get file associations added to your ClickOnce application.&lt;/P&gt;
&lt;H3&gt;Adding File Associations to Your ClickOnce Manifest&lt;/H3&gt;
&lt;P&gt;File associations are adding to your ClickOnce manifest by specifying the fileAssociation tag and it's 4 attributes:&amp;nbsp; extension, description, progid, and defaultIcon. This new tag is in the clickonce.v1 namespace. So, one example looks like this:&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&amp;lt;fileAssociation xmlns="urn:schemas-microsoft-com:clickonce.v1"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; extension=".mwade"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; description="MWadePad Document"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; progid="MWadePad.Document"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; defaultIcon="mwade.ico"&lt;BR&gt;/&amp;gt; &lt;/P&gt;
&lt;P&gt;A little background information about all of these:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;extension: This is the file extension for which your application will be associated. You should make sure that your extension adds the "." to the front of the file. You should aim to use a unique extension for your file association. If, at install time, ClickOnce determines that this file association is already being used, it won't add the necessary system information to register your file association. &lt;/LI&gt;
&lt;LI&gt;description: A brief statement describing the type of document. This appears in the tooltip when hovering over the document, as well as the Type column in explorer when looking at the document.&lt;IMG title="Description Tooltip" style="WIDTH: 222px; HEIGHT: 83px" height=83 alt="Description Tooltip" src="http://blogs.msdn.com/photos/mwade/images/7333611/original.aspx" width=222 mce_src="http://blogs.msdn.com/photos/mwade/images/7333611/original.aspx"&gt;&lt;/LI&gt;
&lt;LI&gt;progid: Helps tie the file extension to your ClickOnce application.&lt;/LI&gt;
&lt;LI&gt;defaultIcon: The icon file from the ClickOnce application to use as the document icon&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Of course, adding file association information to your application manifest is only half of the battle. How can you tell if your application was launched by launching one of its documents? Well, this information is stored in the ActivationData of the current app domain:&lt;/P&gt;
&lt;P&gt;AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0]&lt;/P&gt;
&lt;P&gt;Even if the application is activated through file association, the standard ClickOnce update servicing will be applied.&lt;/P&gt;
&lt;H3&gt;Adding File Associations through Visual Studio&lt;/H3&gt;
&lt;P&gt;There is no fancy UI to allow you to add file associations to your ClickOnce application in Visual Studio. It is also not possible to add the information to your application manifest after publishing, because that would invalidate the signature. So, does that mean you are forced to modify your manifest and then re-sign with mage after publishing? &lt;/P&gt;
&lt;P&gt;Nope. When publishing in Visual Studio, it is possible to add a app.manifest file to your project. This app.manifest acts as an base application manifest, whose information gets added into the generated application manifest. The manifest can be added by clicking the "Enable ClickOnce Security Settings" checkbox on the Security property page.&lt;/P&gt;
&lt;P&gt;For example, here is what my app.manifest file looks like when adding the information from above:&lt;/P&gt;
&lt;P&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;BR&gt;&amp;lt;asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="&lt;A href="http://www.w3.org/2001/XMLSchema-instance" mce_href="http://www.w3.org/2001/XMLSchema-instance"&gt;http://www.w3.org/2001/XMLSchema-instance&lt;/A&gt;"&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;assemblyIdentity version="1.0.0.0" name="MyApplication.app" /&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;security&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;applicationRequestMinimum&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;defaultAssemblyRequest permissionSetReference="Custom" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/applicationRequestMinimum&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/security&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;/trustInfo&amp;gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp; &amp;lt;fileAssociation xmlns="urn:schemas-microsoft-com:clickonce.v1"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; extension=".mwade"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; description="MWadePad Document"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; progid="MWadePad.Document"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; defaultIcon="mwade.ico"&lt;BR&gt;&amp;nbsp; /&amp;gt;&lt;/P&gt;
&lt;P&gt;&amp;lt;/asmv1:assembly&amp;gt;&lt;/P&gt;
&lt;H3&gt;Additional Notes&lt;/H3&gt;
&lt;P&gt;There are some rules and regulations that need to be pointed out for file associations in ClickOnce:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Values must be given for all 4 xml attributes&lt;/LI&gt;
&lt;LI&gt;File associations only work for pure ClickOnce applications. That means that browser-hosted applications and Office documents can't take advantage&lt;/LI&gt;
&lt;LI&gt;The application must be targeting the 3.5 version of the .NET Framework&lt;/LI&gt;
&lt;LI&gt;The application must be full trust&lt;/LI&gt;
&lt;LI&gt;The application must be installed (not run from web)&lt;/LI&gt;
&lt;LI&gt;There is a limit of 8 file associations per application&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7333509" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/7333509.ashx" length="12772" type="application/x-zip-compressed" /></item><item><title>How To: Archive your source files when publishing</title><link>http://blogs.msdn.com/mwade/archive/2007/11/30/how-to-archive-your-source-files-when-publishing.aspx</link><pubDate>Sat, 01 Dec 2007 05:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6622509</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/6622509.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=6622509</wfw:commentRss><description>&lt;P&gt;A long time ago, when I was trying to look up some piece of information for some blog entry, I stumbled upon a neat site for MSBuild tasks: the &lt;A class="" href="http://msbuildtasks.tigris.org/" target=_blank mce_href="http://msbuildtasks.tigris.org/"&gt;MSBuild Community Tasks&lt;/A&gt; site. There are several useful build tasks in there, one of which will be the focus of this post: the &lt;CODE&gt;Zip&lt;/CODE&gt; task. I use this task to package up the source for publication on this blog, and I also use it in the programs I right for entertainment at home. &lt;/P&gt;
&lt;P&gt;My archival system for the programs I write in my spare time is pretty simplistic: when I have finished adding a feature and it feels like a good time to use my application, I zip up the sources. Of course, I'll start adding features later, sometimes months or even years later. When I spend so much time away from the program, I'm worried that I'll mess it up so much that I'll just want to revert back to the previous version and start over (that's right: I don't write unit tests at home). Having this zip archive is really handy. Sure, I could use VSS or something fancy, but frankly the programs I write generally don't warrant anything like that. In this entry, I'm going to show how I use the &lt;CODE&gt;Zip&lt;/CODE&gt; task for archiving.&lt;/P&gt;
&lt;P&gt;Since Visual Studio 8 came along, I tend to distribute my applications via ClickOnce. This is a natural time to do the archiving: publishing your app means its a good time to archive the sources. Ah, but when to use the task? Build has both the &lt;CODE&gt;PreBuild&lt;/CODE&gt; and &lt;CODE&gt;PostBuild&lt;/CODE&gt; events, which is the old-school way of modifying your build via a command-line command (a .bat file, script, or .exe). The new-school way is to override the BeforeBuild or AfterBuild tasks: I don't know of any good way to do this aside from editing the project file by hand, but I have no qualms about that. Wouldn't it be nice if there was a similar extension point for before or after publishing? Good news: there is. &lt;/P&gt;
&lt;P&gt;In Visual Studio, the publish is basically done in 2 phases: there is the build (which in addition to building your binaries, will generate and sign your manifests), and the publish (which pushes all of the appropriate files to the appropriate locations). The first step is all done with MSBuild: it's running msbuild with &lt;CODE&gt;Target="Publish"&lt;/CODE&gt;. The &lt;CODE&gt;Publish&lt;/CODE&gt; target primarily depends on 2 other targets: &lt;CODE&gt;Build&lt;/CODE&gt; and &lt;CODE&gt;PublishOnly&lt;/CODE&gt;:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PublishDependsOn&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;'$(PublishableProject)'=='true'&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt; 
        SetGenerateManifests; 
        Build; 
        PublishOnly 
    &lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PublishDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;If you were to take a closer look at what Build depends on, you would see the &lt;CODE&gt;BeforeBuild&lt;/CODE&gt; and &lt;CODE&gt;AfterBuild&lt;/CODE&gt; targets, as well as the &lt;CODE&gt;PreBuildEvent&lt;/CODE&gt; and &lt;CODE&gt;PostBuildEvent&lt;/CODE&gt; targets. And the &lt;CODE&gt;PublishOnlyDependsOn&lt;/CODE&gt; property is set to:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PublishOnlyDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt; 
        SetGenerateManifests; 
        PublishBuild; 
&lt;B&gt;        BeforePublish; &lt;/B&gt;
        GenerateManifests; 
        CleanPublishFolder; 
        _CopyFilesToPublishFolder; 
        _DeploymentGenerateBootstrapper; 
        ResolveKeySource; 
        _DeploymentSignClickOnceDeployment; 
&lt;B&gt;        AfterPublish &lt;/B&gt;
    &lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PublishOnlyDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;Note the &lt;CODE&gt;BeforePublish&lt;/CODE&gt; and &lt;CODE&gt;AfterPublish&lt;/CODE&gt; extension points. So it is possible to perform some tasks simply by overriding the &lt;CODE&gt;AfterPublish&lt;/CODE&gt; target.&lt;/P&gt;
&lt;P&gt;Figuring out what to zip is a matter of taste. I make the basic assumption that potentially anything under my project directory is a good zipping candidate. However, there are some directories I want to exclude:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;obj&lt;/LI&gt;
&lt;LI&gt;bin&lt;/LI&gt;
&lt;LI&gt;TestResults&lt;/LI&gt;
&lt;LI&gt;publish&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Similarly, there are several file extensions to avoid, mostly because I only care about the sources:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;suo: I think this is a file to store user settings for the solution&lt;/LI&gt;
&lt;LI&gt;pfx: the signing key for my published application. Definitely don't want to include this just in case I give the zip file to someone else without checking the contents&lt;/LI&gt;
&lt;LI&gt;ncb: I think this is intellisense info for VC++ projects&lt;/LI&gt;
&lt;LI&gt;user: the user settings for the project file&lt;/LI&gt;
&lt;LI&gt;zip: prior archives&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;So the full information to do the zipping is below:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Import&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;obj&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;bin&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;TestResults&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;publish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;DirectoryToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;suo&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;pfx&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ncb&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;user&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;zip&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;False&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Visible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ExtensionToNotZip&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
   
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;AfterPublish&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ProjectDir)\**\%(DirectoryToNotZip.FileName)\**&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Include&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;FilesToNotZip&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ProjectDir)\**\*.%(ExtensionToNotZip.FileName)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Include&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;FilesToNotZip&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ProjectDir)\**\*.*&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;Exclude&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(FilesToNotZip)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Include&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;FilesToZip&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;FormatVersion&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationVersion)&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;Revision&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationRevision)&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;FormatType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Path&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;OutputVersion&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;PropertyName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PackageVersion&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
  &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;FormatVersion&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
  &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Zip&lt;/FONT&gt;  &lt;FONT color=#ff0000&gt;Files&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(FilesToZip)&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ZipFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ProjectDir)\$(ProjectName)-$(PackageVersion)-src.zip&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;First, need to import the targets file which contains the &lt;CODE&gt;Zip&lt;/CODE&gt; task information.&lt;/P&gt;
&lt;P&gt;Then, I set the directories and file extensions I don't want to zip in Items. I use items because I build up the list of files to zip by making three calls to &lt;CODE&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/s2y3e43x.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/s2y3e43x.aspx"&gt;CreateItem&lt;/A&gt;&lt;/CODE&gt;. The first 2 generate a complete list of files to not zip, and I use that as the list of files to &lt;CODE&gt;Exclude&lt;/CODE&gt; in the third call. My guess is that I did this in a totally lame way; there's probably some MSBuild stuff I don't know to make the whole process easier, but I'm not entirely sure what it is.&lt;/P&gt;
&lt;P&gt;Next, there is a call to the &lt;CODE&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/microsoft.build.tasks.formatversion_properties.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/microsoft.build.tasks.formatversion_properties.aspx"&gt;FormatVersion&lt;/A&gt;&lt;/CODE&gt; task to figure out what to call my zip file. &lt;CODE&gt;FormatVersion&lt;/CODE&gt; will take the version of the app that I am publishing (1.0.0.0) and change it into something that may be better for file names (1_0_0_0).&lt;/P&gt;
&lt;P&gt;Finally, there is the call to &lt;CODE&gt;Zip&lt;/CODE&gt; to actually do the archiving. The archive ends up in the project directory.&lt;/P&gt;
&lt;P&gt;It would probably be better to zip up my entire solution directory. This would then include the unit tests for my application, and the sources for and class libraries my application is using. I will leave that as an exercise for the reader.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6622509" width="1" height="1"&gt;</description></item><item><title>How To: Update the bootstrapper to install a ClickOnce application using Internet Explorer</title><link>http://blogs.msdn.com/mwade/archive/2007/11/29/how-to-update-the-bootstrapper-to-install-a-clickonce-application-using-internet-explorer.aspx</link><pubDate>Fri, 30 Nov 2007 08:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6608377</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/6608377.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=6608377</wfw:commentRss><description>&lt;P&gt;For completeness sake, I decided to add the postbuild step for using a modified bootstrapper to launch a ClickOnce deployment manifest (.application) file using Internet Explorer. As I detailed &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/11/01/kicking-back-with-motley-crue-sippin-my-lowenbrau.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/11/01/kicking-back-with-motley-crue-sippin-my-lowenbrau.aspx"&gt;here&lt;/A&gt; , the original use for this change was to work-around a ClickOnce liimitation when attempting to install the app via Fire Fox. We have since discovered another use for this type of work-around: the bootstrapper may claim it can not find the .application file on a web server if the application file contains DBCS characters. By using the stub executable to launch Internet Explorer, the problem should be avoided.&lt;/P&gt;The task works by re-defining what the &lt;CODE&gt;PublishOnly&lt;/CODE&gt; target does, replacing &lt;CODE&gt;_DeploymentGenerateBootstrapper&lt;/CODE&gt; with a new target, &lt;CODE&gt;CreateBootstrapper&lt;/CODE&gt;. This target is what calls &lt;CODE&gt;GenerateExtractedBootstrapper&lt;/CODE&gt;. Note that this task is conditioned to run only if the &lt;CODE&gt;IsWebBootstrapper&lt;/CODE&gt; property is true. 
&lt;P&gt;Without more ado, here are the steps necessary to get the modified bootstrapper up and running:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Download and install the binaries for post-build steps (see the attachment of this post)&lt;/LI&gt;
&lt;LI&gt;Unload your project and edit the project file (via the project node's context menu)&lt;/LI&gt;
&lt;LI&gt;Towards the bottom of the file, there should be a comment which starts with &lt;CODE&gt;&lt;FONT color=#008000&gt;To modify your build process&lt;/FONT&gt;&lt;/CODE&gt;. Immediately below the end of that comment, paste the following XML: &lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Import&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\SetupProjects\SetupProjects.Targets&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PublishOnlyDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt; 
        SetGenerateManifests; 
        PublishBuild; 
        BeforePublish; 
        GenerateManifests; 
        CleanPublishFolder; 
        _CopyFilesToPublishFolder; 
        &lt;B&gt;CreateBootstrapper;&lt;/B&gt; 
        ResolveKeySource; 
        _DeploymentSignClickOnceDeployment; 
        AfterPublish 
    &lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PublishOnlyDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 

&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;CreateBootstrapper&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;CallTarget&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Targets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_DeploymentGenerateBootstrapper&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;'$(IsWebBootstrapper)'!='true'&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;CallTarget&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Targets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;GenerateExtractedBootstrapper&lt;/FONT&gt;"
                &lt;FONT color=#ff0000&gt;Condition&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;'$(IsWebBootstrapper)'=='true' and '$(BootstrapperEnabled)'=='true'&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 

&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;GenerateExtractedBootstrapper&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;stub.exe&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(AssemblyName)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;""
                          &lt;FONT color=#ff0000&gt;BootstrapperItems&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(BootstrapperPackage)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BootstrapperComponentsLocation)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;""
                          &lt;FONT color=#ff0000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(TargetCulture)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;FallbackCulture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(FallbackCulture)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PublishDir)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;SupportUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(_DeploymentFormattedSupportUrl)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;Path&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(GenerateBootstrapperSdkPath)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateExtractedBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(TargetDeployManifestFileName)&lt;/FONT&gt;"
                                   &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(_DeploymentFormattedApplicationUrl)&lt;/FONT&gt;"
                                   &lt;FONT color=#ff0000&gt;BootstrapperFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PublishDir)\setup.exe&lt;/FONT&gt;"
                                   &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(_DeploymentFormattedComponentsUrl)&lt;/FONT&gt;"
                                   &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PublishDir)&lt;/FONT&gt;"
                                   &lt;FONT color=#ff0000&gt;StubExe&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\SetupProjects\InstallApplication.exe&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;Notice the steps are a little shorter than that for the setup project. That's because the necessary projects are already msbuild-based. One draw-back to this solution is that IExplorer will flash onto the screen when the bootstrapper is finished, at least until the file handler within Internet Explorer is able to take over. I do wonder if this could be avoided with smarter parameters to Internet Explorer (for example, how could you get the function call to re-use an existing Internet Explorer session). &lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6608377" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/6608377.ashx" length="445952" type="application/octet-stream" /></item><item><title>How To: Update the bootstrapper to accept command-line arguments</title><link>http://blogs.msdn.com/mwade/archive/2007/11/29/how-to-update-the-bootstrapper-to-accept-command-line-arguments.aspx</link><pubDate>Fri, 30 Nov 2007 07:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6608343</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/6608343.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=6608343</wfw:commentRss><description>&lt;P&gt;In the &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/11/01/kicking-back-with-motley-crue-sippin-my-lowenbrau.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/11/01/kicking-back-with-motley-crue-sippin-my-lowenbrau.aspx"&gt;previous blog entry&lt;/A&gt;, I went over the design and implementation of a modified bootstrapper which accepts command-line parameters. For example the bootstrapper which shipped with Visual Studio 2005 is not capable of "doing the right thing" for the following command:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;setup.exe -qn&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;With the modifications, it is possile to get the MSI to install silently. Note the qualifier there: if the bootstrapper is installing prerequisites, it is not possible to get those to siliently install: during the design phase, we were told by the crack team of Microsoft lawyers that some UI (especially the EULA) had to be shown to end-users.&lt;/P&gt;
&lt;P&gt;There are a few other limitations to the modified bootstrapper. Off-hand, I can think of the following:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If the MSI is signed, the signature is NOT verified by the bootstrapper&lt;/LI&gt;
&lt;LI&gt;The error handling within the new bootstrapper (including an MSI which fails to initialize properly) is not well-handled&lt;/LI&gt;
&lt;LI&gt;The testing of the modified bootstrapper is not up to Microsoft's standards&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Without more ado, here are the steps necessary to get the modified bootstrapper up and running:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Download and install the binaries for post-build steps (see the attachment of this post)&lt;/LI&gt;
&lt;LI&gt;Make sure that msbuild is on your path. You can do this by launching devenv from the Visual Studio command prompt&lt;/LI&gt;
&lt;LI&gt;Create your setup project&lt;/LI&gt;
&lt;LI&gt;Copy the template below into a file called "PostBuild.proj" in the same directory as your .vdproj file&lt;/LI&gt;
&lt;LI&gt;Add PostBuild.proj to your setup project&lt;/LI&gt;
&lt;LI&gt;Set Exclude to "True" for PostBuild.proj&lt;/LI&gt;
&lt;LI&gt;Set the PostBuildEvent (in the property grid) to:&lt;BR&gt;&lt;CODE&gt;msbuild.exe /p:Configuration="$(Configuration)" /p:BuiltOutputPath="$(BuiltOuputPath)" /p:ProjectDir="$(ProjectDir)\" /p:BuiltOutputDir="$(ProjectDir)$(Configuration)" "$(ProjectDir)\PostBuild.proj"&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;Turn off prerequisite generation for your setup project&lt;/LI&gt;
&lt;LI&gt;Update the properties in PostBuild.proj to match your particular installer (see images below to see how the MSBuild properties correspond to setup project properties). &lt;B&gt;Do not ignore this step&lt;/B&gt;. At the very least, you need to update the ApplicationFile value in the PostBuild.proj file. (I just spent 15 minutes debugging trying to figure out why my extracted bootstrapper stopped working. It turns out it was because of this)&lt;/LI&gt;
&lt;LI&gt;Build your setup project&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;IMG title="Setup project property grid" style="WIDTH: 405px; HEIGHT: 389px" height=389 alt="Setup project property grid" src="http://blogs.msdn.com/photos/mwade/images/5821517/original.aspx" width=405 mce_src="http://blogs.msdn.com/photos/mwade/images/5821517/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Setup property page" style="WIDTH: 635px; HEIGHT: 447px" height=447 alt="Setup property page" src="http://blogs.msdn.com/photos/mwade/images/5821528/original.aspx" width=635 mce_src="http://blogs.msdn.com/photos/mwade/images/5821528/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Bootstrapper dialog" style="WIDTH: 504px; HEIGHT: 400px" height=400 alt="Bootstrapper dialog" src="http://blogs.msdn.com/photos/mwade/images/5821535/original.aspx" width=504 mce_src="http://blogs.msdn.com/photos/mwade/images/5821535/original.aspx"&gt;&lt;/P&gt;
&lt;TABLE class="" frame=box&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Microsoft Data Access Components 2.8&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.Data.Access.Components.2.8&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;.NET Framework 2.0&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.Net.Framework.2.0&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Crystal Reports for .NET Framework 2.0&lt;/TD&gt;
&lt;TD class=""&gt;BusinessObjects.CrystalReports.NET.2.0&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Microsoft Visual J# .NET Redistributable Package 2.0&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.JSharp.2.0&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Microsoft Visual Studio 2005 Report Viewer&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.ReportViewer.8.0&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Visual C++ Runtime Libraries (x86)&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.Visual.C++.8.0.x86&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Windows Installer 2.0&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.Windows.Installer.2.0&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Windows Installer 3.1&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.Windows.Installer.3.1&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;SQL Server 2005 Express Edition&lt;/TD&gt;
&lt;TD class=""&gt;Microsoft.Sql.Server.Express.1.0&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;
&lt;CAPTION align=bottom&gt;Bootstrapper packages and corresponding Product Codes&lt;/CAPTION&gt;&lt;/TABLE&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Project&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;xmlns&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DefaultTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Import&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\\SetupProjects\\SetupProjects.Targets&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PostBuildDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PostBuildDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
     
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;SetupExtractedBootstrapper.msi&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;SetupExtractedBootstrapper&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;HomeSite&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;$(BuiltOutputDir)&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;BootstrapperPackage&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Microsoft.Net.Framework.2.0&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DependsOnTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PostBuildDependsOn)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;stub.exe&lt;/FONT&gt;"  
                              &lt;FONT color=#ff0000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationName)&lt;/FONT&gt;" 
                              &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"" 
                              &lt;FONT color=#ff0000&gt;BootstrapperItems&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(BootstrapperPackage)&lt;/FONT&gt;"  
                              &lt;FONT color=#ff0000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ComponentsLocation)&lt;/FONT&gt;" 
                              &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"" 
                              &lt;FONT color=#ff0000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(Culture)&lt;/FONT&gt;" 
                              &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
         
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateExtractedBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationFile)&lt;/FONT&gt;"  
                                       &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationUrl)&lt;/FONT&gt;"  
                                       &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ComponentsUrl)&lt;/FONT&gt;"  
                                       &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)&lt;/FONT&gt;" 
                                       &lt;FONT color=#ff0000&gt;BootstrapperFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)\\setup.exe&lt;/FONT&gt;" 
                                       &lt;FONT color=#ff0000&gt;StubExe&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\\SetupProjects\\InstallMsi.exe&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6608343" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/6608343.ashx" length="445952" type="application/octet-stream" /></item><item><title>Kicking back with Motley Crue, sippin' my LowenBrau</title><link>http://blogs.msdn.com/mwade/archive/2007/11/01/kicking-back-with-motley-crue-sippin-my-lowenbrau.aspx</link><pubDate>Fri, 02 Nov 2007 00:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5821469</guid><dc:creator>mwade</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/mwade/comments/5821469.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=5821469</wfw:commentRss><description>&lt;H3&gt;Introduction&lt;/H3&gt;
&lt;P&gt;A common complaint about the bootstrapper that shipped with Visual Studio 8 is that it does not accept command-line parameters for launching the MSI. For example, lots of people want to turn on verbose logging or quiet install. The reason for this limitation is because of how the MSI is installed: instead of using msiexec.exe /i to install the package, a call to MsiInstallProduct is used. MsiInstallProduct only accepts command-line parameters which affect the properties used in the install (which the bootstrapper does dutifully pass along). However, if we are willing to circumvent the use of MsiInstallProduct to install the MSI, it is possible to get the command-line options you desire. I'm going to show how it can be done in this entry. The design will be similar to the design I came up with in December 2005 for a different problem.&lt;/P&gt;
&lt;P&gt;It was around that time that the ClickOnce design-time team was made aware of a slight problem that the ClickOnce runtime already knew about: launching a ClickOnce application through a browser other than IE simply didn't work (and how this was not a violation of the anti-trust settlement still baffles me to this day). There were blogposts pointing out this &lt;A class="" href="http://www.hanselman.com/blog/PermaLink.aspx?guid=7ce42ccd-e531-4d43-a93f-73483c0afd3d" target=_blank mce_href="http://www.hanselman.com/blog/PermaLink.aspx?guid=7ce42ccd-e531-4d43-a93f-73483c0afd3d"&gt;little fact&lt;/A&gt;. The ClickOnce team's official recommendation to all FireFox users was to use Internet Explorer to launch a ClickOnce application (reading that statement makes me roll my eyes, even 2 years later). But there was one little problem with this work-around they were suggesting: the bootstrapper. &lt;/P&gt;
&lt;P&gt;Ahh, the bootstrapper. When the bootstrapper is coming from a website (http://www.foo.com), the bootstrapper's caboose install was nothing more than a ShellExecute to the ClickOnce application (http://www.foo.com/bar.application). The bootstrapper was relying on the shell handler within the OS to route this call to the proper application. It never occurred to the tooling team (us) that FireFox might not be able to correctly handle a .application file. Of course the runtime team knew it wouldn't work: there was no sanctioned way for the FireFox to correctly deal with a .application file. So the runtime team pressured the designtime team to come up with a solution to what was essentially their problem (and if it sounds like I'm still bitter about this, well...). The runtime team's complaint was that their recommended work-around of using IE didn't work when someone used IE to navigate to setup.exe but FireFox was the default browser on the box. After 2 weeks of arguing (which I still can't believe we lost. But I'm not bitter!), our team finally capitulated and agreed to try to come up with a patch for this problem. I wrote up a design document.&lt;/P&gt;
&lt;P&gt;Fortunately, the FireFox community doesn't take 2 weeks to solve a problem. By the time the document was written, someone wrote a &lt;A class="" href="http://www.softwarepunk.com/ffclickonce/" target=_blank mce_href="http://www.softwarepunk.com/ffclickonce/"&gt;FireFox plugin&lt;/A&gt; that was able to handle a ClickOnce application. So, the plan was never acted upon: with the FireFox plugin there was no need to do it.&lt;/P&gt;
&lt;P&gt;But despite the rage I felt (and still feel today, although I'm getting over it. Really), I found the experience to be useful. It was a result of this that I first realized MSBuild was pretty cool. Even though I had written the GenerateBootstrapper task within MSBuild, I didn't really realize what was going on. I wrote the task to serve two different systems: the setup projects (which used COM) and the ClickOnce publishing. I hooked up setup projects to have setup projects use the code in Microsoft.Build.Tasks.dll, while someone else hooked up the task to be used from the ClickOnce publishing system. Although I saw how the GenerateBootstrapper task was part of the publishing system, I still didn't really understand how MSBuild worked. But planning this change helped me realize 2 of the most powerful upsides to MSBuild:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;A user could write their own custom build steps&lt;/LI&gt;
&lt;LI&gt;Those build steps could be inserted anywhere into the build process&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The solution I came up with for the ClickOnce/FireFox problem took advantage of these facts. The simplest fix for the problem would be to change the bootstrapper to always launch Internet Explorer when attempting to launch a ClickOnce application. But in order to do that, we would have had to re-ship the setup.bin that shipped with the .Net SDK and Visual Studio 8. I didn't like that plan given how difficult and expensive it is for Microsoft to produce and support a GDR and how stupid Microsoft would look for producing this so soon after shipping.&lt;/P&gt;
&lt;P&gt;My proposed solution was to change what the bootstrapper launched at the end of the installation: instead of calling ShellExecute on the web-address to the ClickOnce deployment manifest, the bootstrapper would call ShellExecute on a stub exe, which would call Internet Explorer to launch the ClickOnce deployment manifest. And to avoid multiple download security prompts, both of these executables would be stuffed as resources inside of what was termed an "uber-bootstrapper" which would extract both of these files to the installing users temporary directory and run the bootstrapper from there. The uber-bootstrapper leverages the existing bootstrapper and all of the prerequisite checking and running that it does.&lt;/P&gt;
&lt;P&gt;To accomplish this, I proposed a new MSBuild task called GenerateExtractedBootstrapper. This is the task that would take a "regular" bootstrapper along with the stub exe and stuff them into its resources. Then, to have the publish process start calling this task, all a user had to do was modify the PublishOnlyDependsOn property to include the GenerateExtractedBootstrapper. &lt;/P&gt;
&lt;P&gt;I coded this up and it seemed to work. Fortunately, the plans were shelved because someone built the FireFox plugin to handle ClickOnce manifests.&lt;/P&gt;
&lt;P&gt;I always thought there was some merit to this solution, though, and could be applied to other areas as well. A solution like the ClickOnce/FireFox solution could alleviate this command-line issue: instead of a stub exe which launched Internet Explorer, why not have the stub exe launch msiexec? We never pursued this possibility because there wasn't enough general outcry for it.&lt;/P&gt;
&lt;P&gt;Before I start the process of creating this extracted bootstrapper, I did a little re-arranging of the solution that has been developed thus far. These changes include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;I created a new namespace, SetupProjects.WindowsInstaller, which now includes everything that has to do with WindowsInstaller: some of the Utility functions and the WindowsInstaller-specific tasks&lt;/LI&gt;
&lt;LI&gt;Moved windows installer tasks (those that inherited from SetupProjectTask) into SetupProjects.WindowsInstaller.Tasks&lt;/LI&gt;
&lt;LI&gt;Renamed SetupProjectTask to WindowsInstallerTask&lt;/LI&gt;
&lt;LI&gt;Re-worked the tests to fix compiler errors and make sure they contine to pass (they do)&lt;/LI&gt;
&lt;LI&gt;Moved all setup projects and other sample projects into a solution directory, "Examples"&lt;/LI&gt;&lt;/UL&gt;
&lt;H3&gt;Step 1: The original bootstrapper&lt;/H3&gt;
&lt;P&gt;Before we go about creating a fancified bootstrapper, let's first discuss how to go about creating the original bootstrapper. Let's create a new project for our bootstrapper experiments, called SetupExtractedBootstrapper. Add a baseline project file to the project which will contain all of our postbuild steps: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Project&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;xmlns&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;DefaultTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Import&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\SetupProjects\SetupProjects.Targets&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PostBuildDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PostBuildDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DependsOnTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PostBuildDependsOn)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;And set the postbuild event to use MSBuild build the project file:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;msbuild.exe /p:Configuration="$(Configuration)" /p:BuiltOutputPath="$(BuiltOuputPath)" /p:ProjectDir="$(ProjectDir)\" /p:BuiltOutputDir="$(ProjectDir)$(Configuration)" $(ProjectDir)\PostBuild.proj"&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;In order to work, you must make sure that MSBuild is on your path. Launching devenv from the Visual Studio 2005 Command Prompt should be sufficient.&lt;/P&gt;To generate the bootstrapper, you need to use the GenerateBootstrapper task. There are many inputs to this task, but let's quickly enumerate the relevant ones: 
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;ApplicationFile&lt;/CODE&gt;: The name of the caboose (the Msi to launch once all prerequisites have been installed&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;ApplicationName&lt;/CODE&gt;: The name of the application being installed. This value is used with the install UI&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;ApplicationUrl&lt;/CODE&gt;: The expected web address of the bootstrapper and msi it will be installing&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;BootstrapperItems&lt;/CODE&gt;: The list of prerequisites the bootstrapper will install&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;ComponentsLocation&lt;/CODE&gt;: Where the bootstrapper will get the prerequisites it will be installing. Can be one of three values (if blank, &lt;CODE&gt;HomeSite&lt;/CODE&gt; is assumed):&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;HomeSite&lt;/CODE&gt;: Allow the bootstrapper package to be downloaded from the bootstrapper package vendor's website&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Relative&lt;/CODE&gt;: The bootstrapper packages are found relative to the location of setup.exe&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Absolute&lt;/CODE&gt;: Bootstrapper package are downloaded from a specific website&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;CODE&gt;ComponentsUrl&lt;/CODE&gt;: The website to use if &lt;CODE&gt;ComponentsLocation&lt;/CODE&gt; is &lt;CODE&gt;Absolute&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Culture&lt;/CODE&gt;: Specifies which language the bootstrapper UI should be shown in, and the language of the bootstrapper package to install. Can generally be left blank&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;OutputPath&lt;/CODE&gt;: The path on disk to which the bootstrapper will be built&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;All of these values correspond to something in the setup project UI, and several are part of the property set passed into the project file. Unfortunately, it won't be possible to avoid some of the duplication. See the pictures below for a summary of how setup project properties map to GenerateBootstrapper task parameters.&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Setup project property grid" style="WIDTH: 405px; HEIGHT: 389px" height=389 alt="Setup project property grid" src="http://blogs.msdn.com/photos/mwade/images/5821517/original.aspx" width=405 align=absMiddle mce_src="http://blogs.msdn.com/photos/mwade/images/5821517/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Setup project property page" style="WIDTH: 635px; HEIGHT: 447px" height=447 alt="Setup project property page" src="http://blogs.msdn.com/photos/mwade/images/5821528/original.aspx" width=635 align=absMiddle mce_src="http://blogs.msdn.com/photos/mwade/images/5821528/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;IMG title="Prerequisites dialog" style="WIDTH: 504px; HEIGHT: 400px" height=400 alt="Prerequisites dialog" src="http://blogs.msdn.com/photos/mwade/images/5821535/original.aspx" width=504 align=absMiddle mce_src="http://blogs.msdn.com/photos/mwade/images/5821535/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;For this particular example, the following properties should be set to generate the same default bootstrapping experience:&lt;/P&gt;&lt;PRE&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;SetupExtractedBootstrapper.msi&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;SetupExtractedBootstrapper&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;HomeSite&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;$(BuiltOutputDir)&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;BootstrapperPackage&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Microsoft.Net.Framework.2.0&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt;

&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DependsOnTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PostBuildDependsOn)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
&lt;B&gt;    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationFile)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationName)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationUrl)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;BootstrapperItems&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(BootstrapperPackage)&lt;/FONT&gt;"
                          &lt;FONT color=#ff0000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ComponentsLocation)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ComponentsUrl)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(Culture)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; &lt;/B&gt;
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The most notable thing in here is the BootstrapperPackage item. The Include property is set to "Microsoft.Net.Framework.2.0". Where did that value come from? It corresponds to the &lt;CODE&gt;ProductCode&lt;/CODE&gt; of the .Net Framework 2.0 bootstrapper package. These values are discoverable if you know where to look. You can find these by going to the product.xml file which represents the bootstrapper package. Perhaps the easiest way, though, is to open the Prerequisites dialog for your project, check off the packages you want, save the project file, and view it in notepad.&lt;/P&gt;
&lt;P&gt;Make sure the bootstrapper is turned off in the Prerequisites page. Building the project should succeed, and you should see that a setup.exe was created in your build output directory. Running it seems to work as we would expect.&lt;/P&gt;
&lt;H3&gt;Step 2: The uber-bootstrapper&lt;/H3&gt;
&lt;P&gt;In designing the uber-bootstrapper, I'm going to make one important simplifying assumption: the new bootstrapper will not need to work on Windows 98 systems.&lt;/P&gt;
&lt;P&gt;The design of the bootstrapper is pretty simple, and borrows quite a bit from the original bootstrapper. Properties wil be set in the resources of the uber-bootstrapper, and can be extracted by a call to FindResource. Files will also be stuffed into the resources of the uber-bootstrapper. There will be 2 different files: the original bootstrapper, and a stub executable that performs the install. When the uber-bootstrapper is invoked, it will extract its 2 files into a temporary directory. Both of these extracted files needs to know something about its origins in order to do their job. The original bootstrapper needs to know where to get the prerequistes it will be installing as well as the caboose application to invoke. The latter is easy (it's the stub exe that was extracted to the temporary directory). The first is a little more challenging.&lt;/P&gt;
&lt;P&gt;One of the options for the &lt;CODE&gt;ComponentsLocation&lt;/CODE&gt; is "&lt;CODE&gt;Relative&lt;/CODE&gt;". In that case, the relative path should be the source location of the uber-bootstrapper, whether it was from a web-site, CD, or disk path. The bootstrapper is designed to look the caboose in the exact same spot. Because we want the caboose extracted to the temporary directory to be launched, we want the Relative location to be blanked out, signalling the original bootstrapper to look for the caboose next to itself. The uber-bootstrapper will set the the ComponentsUrl to the uber-bootstrapper location of origin to look for application prerequisites. The stub executable will have similar resource information added to it after extraction so that it knows where to download the MSI from.&lt;/P&gt;
&lt;H3&gt;Step 3: The stub executable&lt;/H3&gt;
&lt;P&gt;The stub executable itself is pretty simple. It first figures out where the heck msiexec is by using the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa369548.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/aa369548.aspx"&gt;InstallerLocation registry key&lt;/A&gt; described on MSDN. It next finds the location to the msi it will be launching by looking at its resources. Finally, it constrcuts the full spectrum of command-line parameteres (msiexec -i "Path To Msi" &lt;ADDITIONAL parameters&gt;) and runs ShellExecute. It should be noted that one feature the standard bootstrapper does that the stub I developed does not is make calls to &lt;CODE&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa388208.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/aa388208.aspx"&gt;WinVerifyTrust&lt;/A&gt;&lt;/CODE&gt; to make sure that consistent trust decisions are made regarding a signed bootstrpper package and a signed MSI. Note that the calls are only made when installing from a website. It should be possible to add this information in, I just chose not to to keep the code simpler.&lt;/P&gt;
&lt;H3&gt;Step 4: The final build task&lt;/H3&gt;
&lt;P&gt;Having laid the ground work for the binaries that are necessary for this scheme to work, let's get them built. The properties set in the project file should remain exactly the same. However, their usage by the GenerateBootstrapper task are slightly different:&lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DependsOnTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PostBuildDependsOn)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;&lt;B&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;stub.exe&lt;/FONT&gt;"&lt;/B&gt;
                          &lt;FONT color=#ff0000&gt;ApplicationName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationName)&lt;/FONT&gt;" 
&lt;B&gt;                          &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;""&lt;/B&gt; 
                          &lt;FONT color=#ff0000&gt;BootstrapperItems&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(BootstrapperPackage)&lt;/FONT&gt;"  
                          &lt;FONT color=#ff0000&gt;ComponentsLocation&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ComponentsLocation)&lt;/FONT&gt;"
&lt;B&gt;                          &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;""&lt;/B&gt; 
                          &lt;FONT color=#ff0000&gt;Culture&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(Culture)&lt;/FONT&gt;" 
                          &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;In particular, the &lt;CODE&gt;ApplicationFile&lt;/CODE&gt;, &lt;CODE&gt;ApplicationUrl&lt;/CODE&gt;, and &lt;CODE&gt;ComponentsUrl&lt;/CODE&gt; are all required to change. Don't be alarmed, however: these values simply moved into the &lt;CODE&gt;GenerateExtractedBootstrapper&lt;/CODE&gt; task:&lt;/P&gt;&lt;PRE&gt;    &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GenerateExtractedBootstrapper&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ApplicationFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationFile)&lt;/FONT&gt;"  
                                   &lt;FONT color=#ff0000&gt;ApplicationUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ApplicationUrl)&lt;/FONT&gt;"  
                                   &lt;FONT color=#ff0000&gt;ComponentsUrl&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(ComponentsUrl)&lt;/FONT&gt;"  
                                   &lt;FONT color=#ff0000&gt;OutputPath&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)&lt;/FONT&gt;" 
                                   &lt;FONT color=#ff0000&gt;BootstrapperFile&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(OutputPath)\\setup.exe&lt;/FONT&gt;" 
                                   &lt;FONT color=#ff0000&gt;StubExe&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\\SetupProjects\\InstallMsi.exe&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;H3&gt;Conclusion&lt;/H3&gt;
&lt;P&gt;So there you have it, a way to modify the behavior of your bootstrapper. Sources are included at the tail end of this post in case you want to add further functionality to the installer. There is also a very small set of helper functions for you to create your own stub exectuable. For completeness sake, I included the source for the original motivation for this endeavor: launching a .application file through Internet Explorer. I only tested these on my laptop, which has VS installed. So I'm a little concerned that I screwed up the properties of the VC projects : in particular, I wanted to statically link in the necessary runtimes, and (I think) build without a manifest. If someone finds I did these wrong, I would love to hear it and correct the mistake.&lt;/P&gt;
&lt;H3&gt;Updates&lt;/H3&gt;&lt;I&gt;11/29/2007: There was a bug in the InstallApplication bootstrapper stub (I mixed around a couple of variables). Attached new sources.&lt;/I&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5821469" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/5821469.ashx" length="230438" type="application/x-zip-compressed" /></item><item><title>Moving into Del Boca Vista with the Costanza's (Completed)</title><link>http://blogs.msdn.com/mwade/archive/2007/09/18/moving-into-del-boca-vista-with-the-costanza-s-completed.aspx</link><pubDate>Tue, 18 Sep 2007 21:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4986215</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/4986215.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=4986215</wfw:commentRss><description>&lt;P&gt;The last step in the Vista-related improvements I &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/06/01/moving-into-del-boca-vista-with-the-costanza-s.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/06/01/moving-into-del-boca-vista-with-the-costanza-s.aspx"&gt;outlined several months&lt;/A&gt; ago involves improving the bootstrapper experience on Vista. The problem is that running the bootstrapper on Vista gives a UAC elevation prompt as soon as it is launched. Despite what you may have heard, the bootstrapper isn't some terribly sophisticated piece of software engineering. Really, all it does is launch processes. When the bootstrapper is elevated, the children processes it launches are also elevated. This is both a blessing and a curse. On the one hand, if the bootstrapper is running other installers, those probably should be elevated. On the other hand, it's not always necessary to elevate the final application install (which we refer to as the "caboose"), for example when installing a ClickOnce application or installing an MSI which has the &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx"&gt;LUA Aware&lt;/A&gt; bit set.&lt;/P&gt;
&lt;P&gt;One tempting solution to this problem is to not have the bootstrapper prompt for elevation up front. Its the OS that is causing this prompt to come up, but there is a way to tell the Vista to not prompt for elevation: you can &lt;A class="" href="http://www.microsoft.com/downloads/thankyou.aspx?familyId=ba73b169-a648-49af-bc5e-a2eebb74c16b" target=_blank mce_href="http://www.microsoft.com/downloads/thankyou.aspx?familyId=ba73b169-a648-49af-bc5e-a2eebb74c16b"&gt;add a manifest&lt;/A&gt; to setup.exe so that no eleavtion occurs. And that is correct, this will help the situation of launching the caboose elevated. But it breaks any bootstrapper that needs to install prerequisites, because those packages will need to be elevated.&lt;/P&gt;
&lt;P&gt;"But Mike," you argue, "won't the auto-elevation features of Vista get this solution to work? After all, when I try to run my SQL Express installer manually an elevation prompt comes up." Unfortunately, its not that simple: Vista will issue the prompt for the prerequisites only when the installer processes are launched in a specific manner. Namely, the process has to be launched with &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms647733.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/ms647733.aspx"&gt;ShellExecuteEx&lt;/A&gt;, and specify the verb as "&lt;A class="" href="http://blogs.msdn.com/vistacompatteam/archive/2006/09/25/771232.aspx" target=_blank mce_href="http://blogs.msdn.com/vistacompatteam/archive/2006/09/25/771232.aspx"&gt;runas&lt;/A&gt;". Of course this wasn't known at the time the bootstrapper was getting developed, and as a result that's not how the bootstrapper works. So simply adding a manifest to your setup.exe won't work.&lt;/P&gt;
&lt;P&gt;A more exotic solution is to have the bootstrapper change how the caboose is launched. This is possible to accomplish because of how the bootstrapper is architected: if the caboose is an MSI, it uses MsiInstallProduct to install the MSI. Otherwise, it does a ShellExecute on the caboose. So, if the caboose were actually an executable that would launch the MSI for us, that might work instead. Well, almost: when the bootstrapper is elevated by Vista, the caboose will also be elevated. &lt;/P&gt;
&lt;P&gt;So, the solution needs to get even more exotic: create one executable that is not elevated, which launches the original setup.exe (specifying the "runas" verb), waits for that to finish, and then installs the MSI. And on the surface, this doesn't seem too hard: once again, all that's basically happening is that process are launched, and something waits until each process is finished before launching the next process. In this case there would be 2 child processes: the original bootstrapper (which may launch additional child processes), and then MSI install. And this would be pretty easy except that some of the child processes launched by the original bootstrapper may cause the machine to reboot. Suddenly this becomes a lot harder: now, this new bootstrapper has to detect when the original bootstrapper is causing a machine reboot, and needs to deal with restarting the original bootstrapper when coming out of the reboot.&lt;/P&gt;
&lt;P&gt;I am fully convinced that I could still create a bootstrapper that deals with all of these scenarios. But I won't. The fact of the matter is, the user experience would still be far from ideal, and getting this "uber-bootstrapper" technique fully tested enough to publish to the web just won't happen in a timely fashion. If this were 2006 instead of 2007 and Visual Studio 9 weren't right around the corner, I would make the time. But the fact of the matter is that VS 9 is going to fix this problem for us (with a better solution than I could come up with on this blog), so there's not much sense in writing a blog post thats going to be completely obsolete in a matter of months. And yes, the Visual Studio 9 solution will be free (as part of the Windows SDK) and can be used on Visual Studio 8 projects (I plan on blogging about that once the SDK is officially released).&lt;/P&gt;
&lt;P&gt;So, that will wrap up the Vista-specific post-build steps I wanted to blog about. I'll summarize them below, along with a few words about how Visual Studio 9 (aka Orcas) will address those issues.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;&lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/06/29/hey-man-nice-shot-part-2.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/06/29/hey-man-nice-shot-part-2.aspx"&gt;Making Custom Actions run without impersonation&lt;/A&gt;&lt;/B&gt;&lt;BR&gt;Orcas will be making all custom actions NoImpersonate. 
&lt;P&gt;&lt;B&gt;&lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/08/20/select-play-select-3-0-select.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/08/20/select-play-select-3-0-select.aspx"&gt;Create non-advertised shortcuts&lt;/A&gt;&lt;/B&gt;&lt;BR&gt;Orcas will continue to have all shortcuts be Advertised, so you might want to hold onto these steps. 
&lt;P&gt;&lt;B&gt;&lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx"&gt;LUAAware bit&lt;/A&gt;&lt;/B&gt;&lt;BR&gt;Orcas won't provide any means to access the LUAAware bit. 
&lt;P&gt;&lt;B&gt;&lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/07/30/paging-michael-chiklis-part-2.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/07/30/paging-michael-chiklis-part-2.aspx"&gt;Shield Icons&lt;/A&gt;&lt;/B&gt;&lt;BR&gt;No Vista-related changes to standard Windows Installer dialogs are coming in Orcas. 
&lt;P&gt;&lt;B&gt;Bootstrapper Improvements&lt;/B&gt; &lt;BR&gt;Improvments were made in this area. A manifest was added to setup.exe to not force elevation on Vista. The corresponding changes to how the prerequisites (with the "runas" verb) were also made. As a result, there is no elevation prompt when the bootstrapper is launched, and therefore the caboose install will not automatically be elevated. However, there will be an elevation prompt for every prerequisite that is installed on the machine. So, if your application needs the 3.5 .NET Framework as well as SQL Express, installing your applicatoin via the bootstrapper will cause 2 elevation prompts (1 for each of the components). But this is much better than the VS 8 behavior, which caused an elevation prompt even if nothing was installed.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4986215" width="1" height="1"&gt;</description></item><item><title>Lobster thermidor aux crevettes with a Mornay sauce garnished with truffle paté, brandy and with a fried egg on top and ...</title><link>http://blogs.msdn.com/mwade/archive/2007/09/05/lobster-thermidor-aux-crevettes-with-a-mornay-sauce-garnished-with-truffle-pat-brandy-and-with-a-fried-egg-on-top-and.aspx</link><pubDate>Thu, 06 Sep 2007 01:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4772646</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/4772646.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=4772646</wfw:commentRss><description>&lt;P&gt;A little while after I published my &lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx"&gt;fake mailbag question&lt;/A&gt;, I decided to change my blog settings so that email and comments posted to the blog would be forwarded to my work email address. The blog automatically posts some comments, but it turns out a great deal of them are filtered automatically. How many? I had no idea, until they started getting sent (but not posted).&lt;/P&gt;
&lt;P&gt;I noticed a distinctive trend amongst the spam comments that were passed along (and no, there haven't been any "real" comments or emails passed sent, but I'm not surprised): they all tended to be one word and feature car brands or map-quest in the links. I also noted there were only 4 different words used, with varying amounts of punctuation. &lt;/P&gt;
&lt;P&gt;So out of morbid curiosity, I decided to track all of the comments. Here are the results, in case you are also morbidly curious:&lt;/P&gt;
&lt;TABLE class=""&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;B&gt;Comment&lt;/B&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;B&gt;Frequency&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Cool.&lt;/TD&gt;
&lt;TD class=""&gt;47&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Cool...&lt;/TD&gt;
&lt;TD class=""&gt;49&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Cool!&lt;/TD&gt;
&lt;TD class=""&gt;40&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Interesting...&lt;/TD&gt;
&lt;TD class=""&gt;44&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;interesting&lt;/TD&gt;
&lt;TD class=""&gt;51&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Nice&lt;/TD&gt;
&lt;TD class=""&gt;36&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Nice...&lt;/TD&gt;
&lt;TD class=""&gt;37&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Nice&lt;/TD&gt;
&lt;TD class=""&gt;37&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Sorry :(&lt;/TD&gt;
&lt;TD class=""&gt;44&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;385 comments thus far. &lt;/P&gt;
&lt;P&gt;My favorite? I sort of like the "Sorry :(". For some reason, its good to know the spammers empathize with me, even if the empathy they are feeling is for a technical blog. It shows the spammers are human, too.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4772646" width="1" height="1"&gt;</description></item><item><title>Select-Play-Select-3-0-Select</title><link>http://blogs.msdn.com/mwade/archive/2007/08/20/select-play-select-3-0-select.aspx</link><pubDate>Tue, 21 Aug 2007 08:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4489763</guid><dc:creator>mwade</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/mwade/comments/4489763.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mwade/commentrss.aspx?PostID=4489763</wfw:commentRss><description>&lt;P&gt;&lt;A class="" href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx" target=_blank mce_href="http://blogs.msdn.com/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx"&gt;Last time&lt;/A&gt;, I created an installer with a shortcut in the user's start menu to a very simple application. Once that application is installed, it should be possible to right-click the shortcut and select "Run As Administrator" if you wanted to run the application as an administrator. Unfortunately, that option is not available for the shortcut installed with my Windows Installer package. What gives?&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Context menu for advertised shortcut" style="WIDTH: 311px; HEIGHT: 403px" height=403 alt="Context menu for advertised shortcut" src="http://blogs.msdn.com/photos/mwade/images/4515220/original.aspx" width=311 align=middle mce_src="http://blogs.msdn.com/photos/mwade/images/4515220/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;It turns out that advertised shortcuts do not have this option, while non-advertised shortcuts do. How can someone tell which shortcuts are advertised and which are non-advertised? Well, if you're using a setup project, they are all advertised. To make them non-advertised, we'll need a little post-build magic.&lt;/P&gt;
&lt;P&gt;The &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa371847.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/aa371847.aspx"&gt;Shortcut Table&lt;/A&gt; entry in MSDN describes what it means to have a shortcut be non-advertised:&lt;/P&gt;
&lt;P&gt;&lt;I&gt;The field (Target) should contains a property identifier enclosed by square brackets ([ ]), that is expanded into the file or a folder pointed to by the shortcut.&lt;/I&gt;&lt;/P&gt;
&lt;P&gt;That should clear things up. If not, look at the example in the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/Aa372018.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/Aa372018.aspx"&gt;Specifying Shortcuts walkthrough&lt;/A&gt;: the non-advertised shortcuts are formatted strings of the form [&lt;I&gt;#filekey&lt;/I&gt;]. So the good news is it won't be necessary to write any new tasks to accomplish this. The bad news is, we'll have to do some funky stuff to get MSBuild to do what we need it to do.&lt;/P&gt;
&lt;P&gt;Start by creating the setup project for installing: SetupNonAdvertisedShortcuts. I had this project match a lot of the behavior of SetupNoElevation from last time. I also added another executable, CommandLineArgs.exe from SetupLaunchapplication because I wanted to make this example a little more tricky. I added a shortcut to the SimpleApplication to both the Desktop and the start menu, and added a shortcut to CommandLineArgs.exe to the start menu.&lt;/P&gt;Next, add a postbuild step. Let's just add the project file from last time around, with the usual command-line parameters. This project file will do 2 different tasks: the SummaryInfo update from last time, as well as the non-advertised shortcuts for this time. So, the project file will start off like this: &lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Project&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;xmlns&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DefaultTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Import&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildExtensionsPath)\\SetupProjects\\SetupProjects.Targets&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PostBuildDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;NoElevation;NonAdvertisedShortcuts&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PostBuildDependsOn&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PostBuild&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;DependsOnTargets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PostBuildDependsOn)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
 
    &amp;lt;!--&lt;/FONT&gt;  
            &lt;FONT color=#008000&gt;No Elevation target&lt;/FONT&gt; 
    &lt;FONT color=#0000ff&gt;--&amp;gt; 
     
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;PID_WORDCOUNT&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;15&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PID_WORDCOUNT&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;NoElevation&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GetSummaryInfo&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;MsiFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BuiltOutputPath)&lt;/FONT&gt;" 
                        &lt;FONT color=#ff0000&gt;PropertyIdentifiers&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(PID_WORDCOUNT)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
            &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;SummaryInfo&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;WordCount&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
        &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;GetSummaryInfo&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;AssignValue&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Items&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(WordCount)&lt;/FONT&gt;"  
                     &lt;FONT color=#ff0000&gt;Metadata&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Value&lt;/FONT&gt;"  
                     &lt;FONT color=#ff0000&gt;Operator&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Or&lt;/FONT&gt;"  
                     &lt;FONT color=#ff0000&gt;Value&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;0x8&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
            &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ModifiedItems&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;UpdatedWordCount&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
        &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;AssignValue&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;SetSummaryInfo&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;MsiFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BuiltOutputPath)&lt;/FONT&gt;" 
                        &lt;FONT color=#ff0000&gt;SummaryInfo&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(UpdatedWordCount)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;The PostBuild target is empty, but has 2 dependencies: NoElevation and NonAdvertisedShortcuts. NoElevation is exactly the same stuff as last time. So now its only necessary to define the NonAdvertisedShortcuts target.&lt;/P&gt;
&lt;P&gt;This Target will convert all shortcut to non-advertised shortcuts. It starts with the assumption that all of the shortcuts within the MSI are pointing to files (as opposed to folders). Ideally, this target would grab all of the entries out of the shortcut table and join these with appropriate entries from the file table, based on Component_ column within each table. The Target column would end up being &lt;CODE&gt;[#{File.File}]&lt;/CODE&gt;. For example, if we grabbed the following data out of the Shortcut table:&lt;/P&gt;
&lt;TABLE class="" frame=box&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" colSpan=2&gt;
&lt;CENTER&gt;&lt;B&gt;Shortcuts&lt;/B&gt;&lt;/CENTER&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;Shortcut&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;Component_&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_07FF8550467741DF83F0A745A8F8D3B4&lt;/TD&gt;
&lt;TD class=""&gt;C__4FE2FE1E91B9E7CBEA0CC779BA1485CC&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_0AC4DC265C1E4F39A9AFCD2B592488AE&lt;/TD&gt;
&lt;TD class=""&gt;C__10812A57967D596B3D0597E4309F0C8A&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_0C140C82CCD14896AFC19C6B4F386499&lt;/TD&gt;
&lt;TD class=""&gt;C__4FE2FE1E91B9E7CBEA0CC779BA1485CC&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;and the following out of the File table:&lt;/P&gt;
&lt;TABLE class="" frame=box&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" colSpan=2&gt;
&lt;CENTER&gt;&lt;B&gt;Files&lt;/B&gt;&lt;/CENTER&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;File&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;Component_&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_10812A57967D596B3D0597E4309F0C8A&lt;/TD&gt;
&lt;TD class=""&gt;C__10812A57967D596B3D0597E4309F0C8A&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_4FE2FE1E91B9E7CBEA0CC779BA1485CC&lt;/TD&gt;
&lt;TD class=""&gt;C__4FE2FE1E91B9E7CBEA0CC779BA1485CC &lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;we would end up with a Shortcut data that looked like this:&lt;/P&gt;
&lt;TABLE class="" frame=box&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" colSpan=3&gt;
&lt;CENTER&gt;&lt;B&gt;ModifiedShortcuts&lt;/B&gt;&lt;/CENTER&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;Shortcut&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;Component_&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;I&gt;
&lt;CENTER&gt;Target&lt;/CENTER&gt;&lt;/I&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_07FF8550467741DF83F0A745A8F8D3B4&lt;/TD&gt;
&lt;TD class=""&gt;C__4FE2FE1E91B9E7CBEA0CC779BA1485CC&lt;/TD&gt;
&lt;TD class=""&gt;[#_4FE2FE1E91B9E7CBEA0CC779BA1485CC]&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_0AC4DC265C1E4F39A9AFCD2B592488AE&lt;/TD&gt;
&lt;TD class=""&gt;C__10812A57967D596B3D0597E4309F0C8A&lt;/TD&gt;
&lt;TD class=""&gt;[#_10812A57967D596B3D0597E4309F0C8A]&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;_0C140C82CCD14896AFC19C6B4F386499&lt;/TD&gt;
&lt;TD class=""&gt;C__4FE2FE1E91B9E7CBEA0CC779BA1485CC&lt;/TD&gt;
&lt;TD class=""&gt;[#_4FE2FE1E91B9E7CBEA0CC779BA1485CC]&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;I asked around and an operation like join isn't available in MSBuild: adding the correct File metadata based to the shortcut entry based on the Component_ is tricky. The filtering is possible, but confusing (see this &lt;A class="" href="http://blogs.msdn.com/msbuild/archive/2006/05/18/601146.aspx" target=_blank mce_href="http://blogs.msdn.com/msbuild/archive/2006/05/18/601146.aspx"&gt;sample question&lt;/A&gt; and &lt;A class="" href="http://blogs.msdn.com/msbuild/archive/2006/05/30/610494.aspx" target=_blank mce_href="http://blogs.msdn.com/msbuild/archive/2006/05/30/610494.aspx"&gt;explanation&lt;/A&gt;). However the merging is trickier. A suggestion was made to use the MSBuild task to run a target that does the merging for us, like this: &lt;/P&gt;&lt;PRE&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;_ShortcutColumns&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Component_&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;_FileColumns&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;File&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;_FileColumns&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Component_&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemGroup&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;NonAdvertisedShortcuts&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Select&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;MsiFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BuiltOutputPath)&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;TableName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;File&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;Columns&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(_FileColumns)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Records&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Files&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Select&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;MSBuild&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Projects&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(MSBuildProjectFile)&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;Targets&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;SetShortcutTarget&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;Properties&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Component_=%(Files.Component_);_Target=[#%(Files.File)]&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;TargetOutputs&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ModifiedShortcuts&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;MSBuild&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Update&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;MsiFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BuiltOutputPath)&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;Records&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(ModifiedShortcuts)&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt;                 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;SetShortcutTarget&lt;/FONT&gt;" 
        &lt;FONT color=#ff0000&gt;Outputs&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(ModifiedShortcuts)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;GetPrimaryKeys&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;MsiFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BuiltOutputPath)&lt;/FONT&gt;"  
                    &lt;FONT color=#ff0000&gt;TableName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Shortcut&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;PrimaryKeys&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;_ShortcutColumns&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;GetPrimaryKeys&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Select&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;MsiFileName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;$(BuiltOutputPath)&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;TableName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Shortcut&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;Columns&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(_ShortcutColumns)&lt;/FONT&gt;" 
            &lt;FONT color=#ff0000&gt;Where&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;`Component_`='$(Component_)'&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Records&lt;/FONT&gt;"  &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Shortcuts&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Select&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
 
    &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Include&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;@(Shortcuts)&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;AdditionalMetaData&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Target=$(_Target)&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;&amp;gt; 
        &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Output&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;TaskParameter&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;Include&lt;/FONT&gt;" &lt;FONT color=#ff0000&gt;ItemName&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;=&lt;/FONT&gt;"&lt;FONT color=#0000ff&gt;ModifiedShortcuts&lt;/FONT&gt;" &lt;FONT color=#0000ff&gt;/&amp;gt; 
    &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;CreateItem&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt; 
&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Target&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;In this case, the relevant File information (the Component_ and File key) value is passed through to the SetShortcutTarget target. The SetShortcutTarget gets the primary keys of the Shortcut table, appending the values onto the list of other columns to get (Component_). A call to Select is made, searching for the specific component that was passed as input to the target. The items found then have the Target property set to the input _Target property. Why the _ in front of _Target? MSBuild complained about setting a property called Target. So I made it different by throwing the _ in there. Finally, these Shortcuts are passed back out of the Target via the Outputs value. As the SetShortcutTarget target continues to be called because of the batching, the ModifiedShortcuts list keeps getting bigger and bigger, until all of the File entries have been used, and the msi can now be updated with the Update task.&lt;/P&gt;
&lt;P&gt;Is this technique optimal? Not even close. There are 2 hits into the Windows Installer package with each call to SetShortcutTarget: one to get the primary keys of the Shortcut table, and another to select all shortcuts belonging to a specific component. The call to GetPrimaryKeys could be eliminated simply by including the primary key of the Shortcut table (which is Shortcut) in the ItemGroup list. But based on the MSBuild experts I spoke with, there is no avoiding the multiple calls to Select.&lt;/P&gt;
&lt;P&gt;Is this technique functional? Yes, it gets the job done. Try installing the generated Windows Installer package to a Vista machine. When you're finished, you'll see the Run as Administrator option in your context menu.&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Context menu of non-advertised shortcut" style="WIDTH: 316px; HEIGHT: 446px" height=446 alt="Context menu of non-advertised shortcut" src="http://blogs.msdn.com/photos/mwade/images/4515222/original.aspx" width=316 align=middle mce_src="http://blogs.msdn.com/photos/mwade/images/4515222/original.aspx"&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4489763" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/mwade/attachment/4489763.ashx" length="153647" type="application/x-zip-compressed" /></item></channel></rss>