<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Re-inventing The Wheel</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/mwade/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/mwade/feed.xml</link>
    <description />
    <lastBuildDate>Tue, 16 Apr 2019 05:22:00 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>LightSwitch Application Client Configuration and Signing</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/lightswitch-application-client-configuration-and-signing</link>
      <pubDate>Mon, 13 Jun 2011 15:05:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2011/06/13/lightswitch-application-client-configuration-and-signing/</guid>
      <description><![CDATA[As I mentioned in an earlier entry, LightSwitch Beta 2 added the ability to sign an application....]]></description>
      <content:encoded><![CDATA[<p>As I mentioned in an <a target="_blank" href="http://blogs.msdn.com/b/mwade/archive/2011/06/06/lightswitch-application-deployment-beta1-vs-beta-2.aspx">earlier entry</a>, LightSwitch Beta 2 added the ability to <a target="_blank" href="http://msdn.microsoft.com/en-us/library/gg481772.aspx">sign an application</a>. This can be accomplished on the "Specify a Certificate" page of the publish wizard. But why would anyone want to sign their application? What good does it really do? In this entry, we talk about application types and why signing would be useful.</p>
<p><strong>Types of LightSwitch Applications</strong></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/1057.OOBSpecifyCertificateWizardPage.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/1057.OOBSpecifyCertificateWizardPage.png"></a>The application run by a user which was published from LightSwitch is a Silverlight application. This client application can take one of 2 forms: Desktop or Web. As the property pages and publish wizard state, a Web application runs in the user's browser and is not be able to access other programs. This means that to run the application, a user will have to point their browser to an IIS (or Azure) server which is hosting the application. The server will then serve up the LightSwitch application (packaged as a .xap file)&nbsp;which will&nbsp;run in Silverlight's partial trust sandbox. Whether the application server type is IIS or Windows Azure the experience of running the application client should be fundamentally the same. This type of application is known as a 3-Tier browser application: client, database, and server.</p>
<p>On the other hand, a Desktop application "runs on the user's desktop and can access other programs". So, a desktop application is not ultimately run in the browser (although to initially get to the application, a user may have to use the browser). Instead, it is run in by the Silverlight Out-of-browser Launcher, a tool installed with Silverlight. A desktop application is installed on the client computer, and can be uninstalled using Add/Remove Programs. Once installed, the application is launched from the user's desktop or Start menu. Most notably, the application runs in partial trust. This means that the application can interact with other programs, provided there are entrypoints for those applications. For example, you could have an application write out invoices to Microsoft Word. When you choose a desktop application, LightSwitch modifies the OutOfBrowserSettings.xml file in the client project to tell the Silverlight runtime that the application requires elevated permissions. </p>
<p>Desktop applications come in two forms, depending on the application server type: 2-tier applications or 3-tier applications. A 2-tier application is deployed as a ClickOnce application. The client and server tiers are the same in this case: the user's machine, kind of like what is done when the application is debugged in the LightSwitch IDE. A handy feature within ClickOnce is that the application can be automatically updated when a newer version of the application is available. </p>
<p>A 3-tier desktop application is also hosted on either IIS or Windows Azure, and the experience of running that application should be the same, regardless of which is chosen.</p>
<p><strong>When to Sign</strong></p>
<p>How does signing relate to the application's trust level? It doesn't. The application does not need to be signed to run in elevated trust (that is, to be a desktop application); the trust level is dictated by that OutOfBrowserSettings.xml file that is hidden away. This is handy when debugging your application: you are under no obligation to specify a signing certificate to F5 your application. </p>
<p>Signing is only used for one deployed application type: 3-tier desktop applications. Signing is relevant during the install and update of the application. The application user will be prompted with a security warning prior to installation of the application. The level of the warning can vary based on the state of the application signature. Once installed, the application will automatically detect if a newer version of the application has been published. If so, the application will attempt to install the latest version of the application. However, in order for the auto-update to work, the latest version of the application must be signed with the same key as the previous version.</p>
<p><strong>How to Sign</strong></p>
<p>Application signing is now built into the publish wizard. You can go to the "Specify a Certificate" to turn on application signing by checking the "Specify a certificate" checkbox. There are 3 ways to supply a certificate for the application singing. You may </p>
<ul>
<li>"Select a certificate from the computer's store" shows you the set of relevant certificates that are available on your computer</li>
<li>"Browse for a certificate" allows you to select a certificate file (.pfx) that you may have on your computer</li>
<li>"Create a test certificate" creates a self-signed certificate used to sign the application. You must enter a password for the new cert, which will expire after 1 year</li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/1057.OOBSpecifyCertificateWizardPage.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/1057.OOBSpecifyCertificateWizardPage.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/1057.OOBSpecifyCertificateWizardPage.png" original-url="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/1057.OOBSpecifyCertificateWizardPage.png" border="0" style="display: block; margin-left: auto; margin-right: auto;" /></a></p>
<p>This wizard page also shows additional information about the cert you have selected.&nbsp;By default, the checkbox is checked only if you are application is a 3-tier desktop application.</p>
<p><strong>Running the Application</strong></p>
<p>Once your application has been published to a web server, a client who wants to run that application will navigate to the publish location. The application will start, and the user will be told to install the application by clicking on the Install button:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/8407.OOBInstallScreen.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/8407.OOBInstallScreen.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/8407.OOBInstallScreen.png" original-url="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/8407.OOBInstallScreen.png" border="0" style="display: block; margin-left: auto; margin-right: auto;" /></a></p>
<p>Depending on how the application was signed, the user will then be issued an installation prompt from Silverlight. For applications which have not been signed, or are signed with a self-signed certificate, the&nbsp; user will be presented with an installation screen that looks something like this:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/4722.OOBUnverifiedWarning.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/4722.OOBUnverifiedWarning.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/4722.OOBUnverifiedWarning.png" original-url="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/4722.OOBUnverifiedWarning.png" border="0" style="display: block; margin-left: auto; margin-right: auto;" /></a></p>
<p>Or for a more trusted certificate something like this:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/5140.OOBVerifiedWarning.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/5140.OOBVerifiedWarning.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/5140.OOBVerifiedWarning.png" original-url="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/5140.OOBVerifiedWarning.png" border="0" style="display: block; margin-left: auto; margin-right: auto;" /></a></p>
<p>The user has the ability to choose if they want to install a shortcut to the application on their desktop, on the Start menu, or both, by clicking on the "More options" button on the installation dialog. </p>
<p>After installation, navigating to the publish location shows that a screen telling the user to launch the application from the Start menu. If there are subsequent updates to the application, the application will detect&nbsp; and automatically install these updates:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/1200.OOBUpdateScreen.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/1200.OOBUpdateScreen.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/1200.OOBUpdateScreen.png" original-url="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/1200.OOBUpdateScreen.png" border="0" style="display: block; margin-left: auto; margin-right: auto;" /></a></p>
<p>Unless, that is, the original application was not signed, or was signed with a different cert. In that case, the update would fail, and you would have to uninstall and then re-install the application:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/6746.OOBUpdateError.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/6746.OOBUpdateError.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/67/51/6746.OOBUpdateError.png" original-url="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-67-51/6746.OOBUpdateError.png" border="0" style="display: block; margin-left: auto; margin-right: auto;" /></a></p>
<p>Signing your 3-tier desktop application helps ensure the application upgrade works.</p>
<p><strong>Additional Resources</strong><br />LightSwitch documentation: <a target="_blank" href="http://msdn.microsoft.com/en-us/library/gg481772.aspx">Signing a XAP File by Using a Certificate</a><br /><a target="_parent" href="http://msdn.microsoft.com/en-us/library/dd550721.aspx">Silverlight Out-of-browser support</a></p>]]></content:encoded>
    </item>
    <item>
      <title>LightSwitch Application Deployment: Beta1 vs. Beta 2</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/lightswitch-application-deployment-beta1-vs-beta-2</link>
      <pubDate>Mon, 06 Jun 2011 11:42:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2011/06/06/lightswitch-application-deployment-beta1-vs-beta-2/</guid>
      <description><![CDATA[I haven't written a blog post for quite a while. Since my last blog entry, I moved from working on...]]></description>
      <content:encoded><![CDATA[<p>I haven't written a blog post for quite a while. Since my last blog entry, I moved from working on ClickOnce tooling to <a target="_blank" href="http://blogs.msdn.com/controlpanel/blogs/posteditor.aspx/LightSwitch">LightSwitch</a>. I am still working on deployment stuff, so now you know who to blame.</p>
<p>I meant to write a quick overview of LightSwitch application deployment after Beta 1 shipped, but I never got around to it. And then some of my colleagues started <a target="_blank" href="http://blogs.msdn.com/b/lightswitch/">writing some good</a> stuff about LightSwitch and deployment, so I figured why screw things up by adding my take on things?</p>
<p>I've since come around: hopefully there is a spot for my behind-the-scenes insight into LightSwitch and application deployment. So I'm back, baby! With a vengeance!</p>
<p>Let's start off with a softball of a post: How has deployment changed between Beta 1 and Beta 2? Here's a quick summary.</p>
<p><strong>Publish to Azure</strong> This is by far the biggest deployment change in Beta 2. If you have a Windows Azure account, you can publish your LightSwitch application to it. The publish wizard should walk you through the steps to get your application onto Azure. And of course its also possible to publish your data to SQL Azure as well. Andy Kung has a <a target="_blank" href="http://blogs.msdn.com/b/lightswitch/archive/2011/03/18/step-by-step-how-to-publish-to-windows-azure-andy-kung.aspx">nice writeup</a> of how to publish your LightSwitch application to Windows Azure.</p>
<p><strong>Server Runtime is Copied Locally</strong> In Beta 1 there was a separate runtime that needed to be installed on the server for the server-side code. Such a runtime is highly impactful to the hosting machine (which can be good, but can also be bad). In Beta 2, LightSwitch no longer requires a runtime to be installed to the server to run a LightSwitch application.</p>
<p><strong>Publishing to a Web Hosting Company</strong> Publishing the server runtime with the application opens the scenario of publishing to a web hoster, without the need for that hoster to have files installed to the Global Assembly Cache. However, publishing a LightSwitch project uses an extension&nbsp; for MSDeploy to help configure the web application. The provider is shipped in a separate installer, titled the Visual Studio LightSwitch Deployment Prerequisites. If your web hoster does not have the provider available, it is possible to bypass this configuration step while publishing simply by selecting this option within the Server Configuration page of the Publish Wizard. You will then have to make sure the web location is properly configured to handle a LightSwitch application by adding the application to a .NET 4.0 application pool, and potentially configuring the application Authentication type.</p>
<p><strong>Support for Additional IIS Platforms</strong> A common misconception for Beta 1 was that the only IIS platform capable of hosting a LightSwitch application was Windows 2008. This was not entirely true: it was possible to generate an MSDeploy package of your LightSwitch application and install it on Windows 7 and IIS 7, or even Windows 2003 Server and IIS 6. However, it was not possible to publish from the IDE directly to either of those platforms. For LightSwitch Beta 1, the remote publish scenario was based on the capabilities of Visual Studio 2010 Beta 2. However, between VS 2010 Beta 2 and RTM, the One-Click publish feature for web applications added the capability of publishing directly to IIS 6 and Windows 7. LightSwitch Beta 2 follows this lead. The server requires MSDeploy with the Web Deployment Agent Service installed. You can also deploy to localhost, provided you start LightSwitch with administrative privileges.</p>
<p><strong>Database Schema Publishing</strong> has been updated as well. The publish wizard handles 2 different connection strings: one for publishing the database schema (the "administrator connection"), and a second for accessing that data from the application (the "user connection"). The administrator connection obviously needs more permissions than the user connection would typically require, but if you want to use the same for both connection strings that is allowed. If you want to create a new login for the for the user connection string, that capability is also added to the Database Connections wizard page.</p>
<p><strong>Xap Signing </strong>A desktop application deployed to IIS or Windows Azure will also check for updates as part of application launch. Unfortunately, the update is not applied unless the .xap file is properly signed. LightSwitch Beta 1 provided no means to sign the application, a problem that has been corrected with LightSwitch Beta 2. (Update 6/13/2011: Read more about this topic <a target="_parent" href="http://blogs.msdn.com/b/mwade/archive/2011/06/13/lightswitch-application-client-configuration-and-signing.aspx">here</a>).</p>
<p>There is a lot more that could be written about all of these topics. And there will be! As each new entry is written, this space will be updated with a link to the in-depth examination of the issue.</p>]]></content:encoded>
    </item>
    <item>
      <title>How To: Generate publish.htm with MSBuild</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/how-to-generate-publish-htm-with-msbuild</link>
      <pubDate>Sat, 28 Feb 2009 18:27:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2009/02/28/how-to-generate-publish-htm-with-msbuild/</guid>
      <description><![CDATA[One of the features Visual Studio provides when publishing is the generation of a web page that...]]></description>
      <content:encoded><![CDATA[<P>One of the features Visual Studio provides when publishing is the generation of a <A href="http://www.familywade.net/applications/MoneyMatrix/publish.htm" mce_href="http://www.familywade.net/applications/MoneyMatrix/publish.htm">web page</A> 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.</P>
<P>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.</P>
<P><B>Background: How publish.htm is generated</B></P>
<P>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:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#2b91af>xsl:template</FONT>  <FONT color=#ff0000>match</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>PageData</FONT>"<FONT color=#0000ff>&gt; 
 
  &lt;</FONT><FONT color=#a31515>HTML</FONT><FONT color=#0000ff>&gt; 
 
    &lt;</FONT><FONT color=#a31515>HEAD</FONT><FONT color=#0000ff>&gt; 
      &lt;</FONT><FONT color=#a31515>TITLE</FONT><FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#2b91af>xsl:value-of</FONT>  <FONT color=#ff0000>select</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>ProductName</FONT>"<FONT color=#0000ff>/&gt; 
      &lt;/</FONT><FONT color=#a31515>TITLE</FONT><FONT color=#0000ff>&gt; 
      &lt;</FONT><FONT color=#a31515>META</FONT>  <FONT color=#ff0000>HTTP-EQUIV</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>Content-Type</FONT>"  <FONT color=#ff0000>CONTENT</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>text/html; charset=utf-8</FONT>"<FONT color=#0000ff>/&gt;</FONT>
</PRE>
<P>The stylesheet reads info out of an XML fragment, of which <CODE>PageData</CODE> is the root element. A scan of the stylesheet shows that the data used to transform the stylesheet may look something like this:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>PageData</FONT>  <FONT color=#ff0000>xmlns:xsi</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>http://www.w3.org/2001/XMLSchema-instance</FONT>"  <FONT color=#ff0000>xmlns:xsd</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>http://www.w3.org/2001/XMLSchema</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>ApplicationVersion</FONT><FONT color=#0000ff>&gt;</FONT>1.0.0.0<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>ApplicationVersion</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>InstallUrl</FONT><FONT color=#0000ff>&gt;</FONT>ConsoleApplication.application<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>InstallUrl</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>ProductName</FONT><FONT color=#0000ff>&gt;</FONT>ConsoleApplication<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>ProductName</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublisherName</FONT><FONT color=#0000ff>&gt;</FONT>Mike Wade<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublisherName</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>SupportUrl</FONT><FONT color=#0000ff>&gt;</FONT>http://blogs.msdn.com/mwade<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>SupportUrl</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>Prerequisites</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Prerequisite</FONT><FONT color=#0000ff>&gt;</FONT>.NET Framework 3.5<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Prerequisite</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Prerequisite</FONT><FONT color=#0000ff>&gt;</FONT>Windows Installer 3.1<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Prerequisite</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>Prerequisites</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>RuntimeVersion</FONT><FONT color=#0000ff>&gt;</FONT>2.0.0<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>RuntimeVersion</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>BootstrapperText</FONT><FONT color=#0000ff>&gt;</FONT>The following prerequisites are required:<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>BootstrapperText</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>ButtonLabel</FONT><FONT color=#0000ff>&gt;</FONT>Install<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>ButtonLabel</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>BypassText</FONT><FONT color=#0000ff>&gt;</FONT>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.<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>BypassText</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>HelpText</FONT><FONT color=#0000ff>&gt;</FONT>ClickOnce and .NET Framework Resources<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>HelpText</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>HelpUrl</FONT><FONT color=#0000ff>&gt;</FONT>http://msdn.microsoft.com/clickonce<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>HelpUrl</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>NameLabel</FONT><FONT color=#0000ff>&gt;</FONT>Name:<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>NameLabel</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublisherLabel</FONT><FONT color=#0000ff>&gt;</FONT>Publisher:<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublisherLabel</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>SupportText</FONT><FONT color=#0000ff>&gt;</FONT>Mike Wade Customer Support<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>SupportText</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>VersionLabel</FONT><FONT color=#0000ff>&gt;</FONT>Version:<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>VersionLabel</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>PageData</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>The xml input contains 3 basic types of information:</P>
<OL>
<LI>Application specific information (publisher, product, install, etc.)</LI>
<LI>Application prerequisite information (bootsrapper packages installed, a .NET Framework runtime used by the jscript)</LI>
<LI>Static strings read from Microsoft.VisualStudio.Publish.dll</LI></OL>
<P><B>A build task to create publish.htm</B></P>Let's create a build task that will create the publish web page. <PRE><FONT color=#0000ff>namespace</FONT> CreatePublishWebPage 
{ 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>class</FONT> <FONT color=#2b91af>CreatePublishWebPage</FONT> : <FONT color=#2b91af>Task</FONT> 
    { 
    } 
}
</PRE>
<P>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:</P><PRE><FONT color=#0000ff>public</FONT> <FONT color=#0000ff>struct</FONT> <FONT color=#2b91af>PageData</FONT> 
{ 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> ApplicationVersion; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> InstallUrl; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> ProductName; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> PublisherName; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> SupportUrl; 
 
    [<FONT color=#2b91af>XmlArray</FONT>()] 
    [<FONT color=#2b91af>XmlArrayItem</FONT>(<FONT color=#a31515>"Prerequisite"</FONT>)] 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT>[] Prerequisites; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> RuntimeVersion; 
 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> BootstrapperText; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> ButtonLabel; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> BypassText; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> HelpText; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> HelpUrl; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> NameLabel; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> PublisherLabel; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> SupportText; 
    <FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> VersionLabel; 
}
</PRE>
<P>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.</P>
<P>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.</P>
<P>Finally, the other information will be part of the build tasks resources, which I also pulled out of Microsoft.VisualStudio.Publish.dll</P>
<P>With this in mind, it is easy to stub out the task, like this:</P><PRE>[<FONT color=#2b91af>Required</FONT>] 
<FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> ApplicationManifestFileName { <FONT color=#0000ff>get</FONT>; <FONT color=#0000ff>set</FONT>; } 
 
[<FONT color=#2b91af>Required</FONT>] 
<FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> DeploymentManifestFileName { <FONT color=#0000ff>get</FONT>; <FONT color=#0000ff>set</FONT>; } 
 
[<FONT color=#2b91af>Required</FONT>] 
<FONT color=#0000ff>public</FONT> <FONT color=#0000ff>bool</FONT> BootstrapperEnabled { <FONT color=#0000ff>get</FONT>; <FONT color=#0000ff>set</FONT>; } 
 
<FONT color=#0000ff>public</FONT> <FONT color=#2b91af>ITaskItem</FONT>[] BootstrapperPackages { <FONT color=#0000ff>get</FONT>; <FONT color=#0000ff>set</FONT>; } 
 
<FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> TemplateFileName { <FONT color=#0000ff>get</FONT>; <FONT color=#0000ff>set</FONT>; } 
 
<FONT color=#0000ff>public</FONT> <FONT color=#0000ff>string</FONT> OutputFileName { <FONT color=#0000ff>get</FONT>; <FONT color=#0000ff>set</FONT>; } 
 
<FONT color=#0000ff>public</FONT> <FONT color=#0000ff>override</FONT> <FONT color=#0000ff>bool</FONT> Execute() 
{ 
    <FONT color=#2b91af>PageData</FONT> data = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>PageData</FONT>(); 
 
    WriteManifestInfo(<FONT color=#0000ff>ref</FONT> data); 
    <FONT color=#0000ff>if</FONT> (BootstrapperEnabled) 
    { 
        WriteBootstrapperInfo(<FONT color=#0000ff>ref</FONT> data); 
    } 
    WriteStaticText(<FONT color=#0000ff>ref</FONT> data); 
 
    XmlTransform(data); 
     
    <FONT color=#0000ff>return</FONT> <FONT color=#0000ff>true</FONT>; 
}
</PRE>
<P>Now, let's get to th actual meat of the task, starting with <CODE>WriteManifestInfo</CODE>. The code will use the <CODE>ManifestUtilities</CODE> API to directly access the appropriate properties from <CODE>DeployManifest</CODE>. <CODE>ManifestUtilities</CODE> 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:</P><PRE><FONT color=#0000ff>using</FONT> Microsoft.Build.Tasks.Deployment.ManifestUtilities;

<FONT color=#0000ff>private</FONT> <FONT color=#2b91af>DeployManifest</FONT> deployManifest = <FONT color=#0000ff>null</FONT>; 
<FONT color=#0000ff>private</FONT> <FONT color=#2b91af>DeployManifest</FONT> DeployManifest 
{ 
    <FONT color=#0000ff>get</FONT> 
    { 
        <FONT color=#0000ff>if</FONT> (deployManifest == <FONT color=#0000ff>null</FONT>) 
        { 
            deployManifest = (<FONT color=#2b91af>DeployManifest</FONT>)<FONT color=#2b91af>ManifestReader</FONT>.ReadManifest(<FONT color=#0000ff>this</FONT>.DeploymentManifestFileName, <FONT color=#0000ff>true</FONT>); 
        } 
        <FONT color=#0000ff>return</FONT> deployManifest; 
    } 
} 
 
 <FONT color=#0000ff>private</FONT> <FONT color=#0000ff>void</FONT> WriteManifestInfo(<FONT color=#0000ff>ref</FONT> <FONT color=#2b91af>PageData</FONT> data) 
{ 
    data.ApplicationVersion = DeployManifest.AssemblyIdentity.Version; 
    data.InstallUrl = <FONT color=#2b91af>Path</FONT>.GetFileName(DeployManifest.SourcePath); 
    data.ProductName = DeployManifest.Product; 
    data.PublisherName = DeployManifest.Publisher; 
    data.SupportUrl = DeployManifest.SupportUrl; 
}
</PRE>
<P>The code uses a simple accessor to access the <CODE>DeployManifest</CODE>, and then writes appropriate information to the page data.</P>
<P>Dealing with prerequisites is a little more complicated in. There are 3 important steps in the process:</P>
<OL>
<LI>Add a list of all installed prerequisites into the Prerequisites field</LI>
<LI>Determine if the only prerequisites are .NET Frameowrk (or Windows Installer 3.1) only</LI>
<LI>Determine the required framework version based on the presence of specific .NET assemblies in the application manifest</LI></OL>
<P>For this last point, the <CODE>WindowsBase</CODE> prereq corresponds to the 3.0 framework, while <CODE>System.Core</CODE> corresponds to the 3.5 framework. The prereqs are looked by examining the <CODE>AssemblyReferences</CODE> of the application manifest. Now for the actual code:</P><PRE><FONT color=#0000ff>using</FONT> Microsoft.Build.Tasks.Deployment.Bootstrapper;

<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>static</FONT> <FONT color=#0000ff>readonly</FONT> <FONT color=#0000ff>string</FONT>[] DOTNET30AssemblyIdentity = { <FONT color=#a31515>"WindowsBase"</FONT>, <FONT color=#a31515>"3.0.0.0"</FONT>, <FONT color=#a31515>"31bf3856ad364e35"</FONT>, <FONT color=#a31515>"neutral"</FONT>, <FONT color=#a31515>"msil"</FONT> }; 
<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>static</FONT> <FONT color=#0000ff>readonly</FONT> <FONT color=#0000ff>string</FONT>[] DOTNET35AssemblyIdentity = { <FONT color=#a31515>"System.Core"</FONT>, <FONT color=#a31515>"3.5.0.0"</FONT>, <FONT color=#a31515>"b77a5c561934e089"</FONT>, <FONT color=#a31515>"neutral"</FONT>, <FONT color=#a31515>"msil"</FONT> }; 
<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>const</FONT> <FONT color=#0000ff>string</FONT> METADATA_INSTALL = <FONT color=#a31515>"Install"</FONT>; 
<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>const</FONT> <FONT color=#0000ff>string</FONT> PRODUCT_CODE_DOTNET_PREFIX = <FONT color=#a31515>"Microsoft.Net.Framework."</FONT>; 
<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>const</FONT> <FONT color=#0000ff>string</FONT> PRODUCT_CODE_WINDOWS_INSTALLER = <FONT color=#a31515>"Microsoft.Windows.Installer.3.1"</FONT>;

<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>void</FONT> WriteBootstrapperInfo(<FONT color=#0000ff>ref</FONT> <FONT color=#2b91af>PageData</FONT> data) 
{ 
    <FONT color=#2b91af>BootstrapperBuilder</FONT> builder = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>BootstrapperBuilder</FONT>(); 
    <FONT color=#2b91af>ProductCollection</FONT> products = builder.Products; 
     
    <FONT color=#0000ff>bool</FONT> isDotNetOnly = <FONT color=#0000ff>true</FONT>; 
    <FONT color=#2b91af>List</FONT>&lt;<FONT color=#0000ff>string</FONT>&gt; productNames = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>List</FONT>&lt;<FONT color=#0000ff>string</FONT>&gt;(); 
    <FONT color=#0000ff>foreach</FONT> (<FONT color=#2b91af>ITaskItem</FONT> bootstrapperPackage <FONT color=#0000ff>in</FONT> <FONT color=#0000ff>this</FONT>.BootstrapperPackages) 
    { 
        <FONT color=#0000ff>string</FONT> productCode = bootstrapperPackage.ItemSpec; 
        <FONT color=#0000ff>bool</FONT> install = <FONT color=#0000ff>false</FONT>; 
        <FONT color=#0000ff>bool</FONT>.TryParse(bootstrapperPackage.GetMetadata(METADATA_INSTALL), <FONT color=#0000ff>out</FONT> install); 
        <FONT color=#0000ff>if</FONT> (install) 
        { 
            <FONT color=#0000ff>string</FONT> productName = productCode; 
            <FONT color=#2b91af>Product</FONT> product = products.Product(productCode); 
            <FONT color=#0000ff>if</FONT> (product != <FONT color=#0000ff>null</FONT>) 
            { 
                productName = product.Name; 
            } 
            productNames.Add(productName); 
 
            <FONT color=#0000ff>if</FONT> (!productCode.StartsWith(PRODUCT_CODE_DOTNET_PREFIX, <FONT color=#2b91af>StringComparison</FONT>.OrdinalIgnoreCase) &amp;&amp; 
                !productCode.Equals(PRODUCT_CODE_WINDOWS_INSTALLER, <FONT color=#2b91af>StringComparison</FONT>.OrdinalIgnoreCase)) 
            { 
                isDotNetOnly = <FONT color=#0000ff>false</FONT>; 
            } 
        } 
    } 
 
    data.Prerequisites = productNames.ToArray(); 
    <FONT color=#0000ff>if</FONT> (data.Prerequisites.Length &gt; 0 &amp;&amp; isDotNetOnly) 
    { 
        data.RuntimeVersion = GetRuntimeVersion(); 
    } 
} 
 
<FONT color=#0000ff>private</FONT> <FONT color=#0000ff>string</FONT> GetRuntimeVersion() 
{ 
    <FONT color=#0000ff>string</FONT> version = <FONT color=#a31515>"2.0.0"</FONT>; 
    <FONT color=#2b91af>AssemblyReference</FONT> dotNet30AssemblyReference = ApplicationManifest.AssemblyReferences.Find(CreateAssemblyIdentity(DOTNET30AssemblyIdentity)); 
    <FONT color=#0000ff>if</FONT> (dotNet30AssemblyReference != <FONT color=#0000ff>null</FONT> &amp;&amp; dotNet30AssemblyReference.IsPrerequisite) 
    { 
        version = <FONT color=#a31515>"3.0.0"</FONT>; 
    } 
    <FONT color=#2b91af>AssemblyReference</FONT> dotNet35AssemblyReference = ApplicationManifest.AssemblyReferences.Find(CreateAssemblyIdentity(DOTNET35AssemblyIdentity)); 
    <FONT color=#0000ff>if</FONT> (dotNet35AssemblyReference != <FONT color=#0000ff>null</FONT> &amp;&amp; dotNet35AssemblyReference.IsPrerequisite) 
    { 
        version = <FONT color=#a31515>"3.5.0"</FONT>; 
    } 
 
    <FONT color=#0000ff>return</FONT> version; 
} 
 
<FONT color=#0000ff>private</FONT> <FONT color=#2b91af>AssemblyIdentity</FONT> CreateAssemblyIdentity(<FONT color=#0000ff>string</FONT>[] info) 
{ 
    <FONT color=#0000ff>return</FONT> <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>AssemblyIdentity</FONT>(info[0], info[1], info[2], info[3], info[4]);  
}
</PRE>
<P>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.</P><PRE><FONT color=#0000ff>private</FONT> <FONT color=#0000ff>void</FONT> WriteStaticText(<FONT color=#0000ff>ref</FONT> <FONT color=#2b91af>PageData</FONT> data) 
{ 
    data.BootstrapperText = Properties.<FONT color=#2b91af>Resources</FONT>.BootstrapperText; 
    <FONT color=#0000ff>if</FONT> (deployManifest.Install) 
    { 
        data.ButtonLabel = Properties.<FONT color=#2b91af>Resources</FONT>.InstallButtonLabel; 
    } 
    <FONT color=#0000ff>else</FONT> 
    { 
        data.ButtonLabel = Properties.<FONT color=#2b91af>Resources</FONT>.RunButtonLabel; 
    } 
    data.BypassText = Properties.<FONT color=#2b91af>Resources</FONT>.BypassText; 
    data.HelpText = Properties.<FONT color=#2b91af>Resources</FONT>.HelpText; 
    data.HelpUrl = Properties.<FONT color=#2b91af>Resources</FONT>.HelpUrl; 
    data.NameLabel = Properties.<FONT color=#2b91af>Resources</FONT>.NameLabel; 
    data.PublisherLabel = Properties.<FONT color=#2b91af>Resources</FONT>.PublisherLabel; 
    data.SupportText = <FONT color=#0000ff>string</FONT>.Format(<FONT color=#2b91af>CultureInfo</FONT>.CurrentCulture, Properties.<FONT color=#2b91af>Resources</FONT>.SupportText, DeployManifest.Publisher); 
    data.VersionLabel = Properties.<FONT color=#2b91af>Resources</FONT>.VersionLabel; 
}
</PRE>
<P>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.</P><PRE><FONT color=#0000ff>private</FONT> <FONT color=#0000ff>void</FONT> XmlTransform(<FONT color=#2b91af>PageData</FONT> data) 
{ 
    <FONT color=#0000ff>if</FONT> (!<FONT color=#0000ff>string</FONT>.IsNullOrEmpty(<FONT color=#0000ff>this</FONT>.OutputFileName)) 
    { 
        <FONT color=#008000>// Serialize all of the web page data</FONT> 
        <FONT color=#2b91af>XmlSerializer</FONT> serializer = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>XmlSerializer</FONT>(data.GetType()); 
        <FONT color=#2b91af>MemoryStream</FONT> dataStream = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>MemoryStream</FONT>(); 
        <FONT color=#2b91af>StreamWriter</FONT> streamWriter = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>StreamWriter</FONT>(dataStream); 
        serializer.Serialize(streamWriter, data); 
        dataStream.Position = 0; 
        <FONT color=#2b91af>XmlReader</FONT> dataReader = <FONT color=#2b91af>XmlReader</FONT>.Create(dataStream); 
 
        <FONT color=#008000>// Set up the transform</FONT> 
        <FONT color=#2b91af>XmlDocument</FONT> stylesheet = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>XmlDocument</FONT>(); 
        <FONT color=#0000ff>if</FONT> (!<FONT color=#0000ff>string</FONT>.IsNullOrEmpty(TemplateFileName)) 
        { 
            stylesheet.Load(TemplateFileName); 
        } 
        <FONT color=#0000ff>else</FONT> 
        { 
            stylesheet.LoadXml(Properties.<FONT color=#2b91af>Resources</FONT>.PublishPage); 
        } 
        <FONT color=#2b91af>XslCompiledTransform</FONT> transform = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>XslCompiledTransform</FONT>(); 
        transform.Load(stylesheet); 
 
        <FONT color=#008000>// Perform the transform, writing to the output file</FONT> 
        <FONT color=#0000ff>using</FONT> (<FONT color=#2b91af>XmlTextWriter</FONT> outputFile = <FONT color=#0000ff>new</FONT> <FONT color=#2b91af>XmlTextWriter</FONT>(<FONT color=#0000ff>this</FONT>.OutputFileName, <FONT color=#2b91af>Encoding</FONT>.UTF8)) 
        { 
            outputFile.Formatting = <FONT color=#2b91af>Formatting</FONT>.Indented; 
            transform.Transform(dataReader, outputFile); 
        } 
    } 
}
</PRE><B>
<P>Using the <CODE>CreatePublishWebPage</CODE> Task</P></B>To use the task, you need only to modify your project file, overriding the "<CODE>AfterPublish</CODE>" target: <PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>UsingTask</FONT>  <FONT color=#ff0000>TaskName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>CreatePublishWebPage</FONT>"  <FONT color=#ff0000>AssemblyFile</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(MSBuildExtensionsPath)\\CreatePublishWebPage.dll</FONT>" <FONT color=#0000ff>/&gt; 
&lt;</FONT><FONT color=#a31515>Target</FONT>  <FONT color=#ff0000>Name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>AfterPublish</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>CreatePublishWebPage</FONT>  <FONT color=#ff0000>ApplicationManifestFileName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)</FONT>"  
                          
                        <FONT color=#ff0000>DeploymentManifestFileName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(PublishDir)$(TargetDeployManifestFileName)</FONT>"  
                          
                        <FONT color=#ff0000>BootstrapperEnabled</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(BootstrapperEnabled)</FONT>"  
                          
                        <FONT color=#ff0000>BootstrapperPackages</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(BootstrapperPackage)</FONT>"  
                          
                        <FONT color=#ff0000>OutputFileName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(PublishDir)$(WebPage)</FONT>" <FONT color=#0000ff>/&gt; 
&lt;/</FONT><FONT color=#a31515>Target</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>The above snippet writes the publish.htm to the app.publish folder under your config's output (e.g. <CODE>bin\debug\app.publish</CODE>). 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 (<CODE>BuildingInsideVisualStudio</CODE>) as well as whether or not the user wants to generate a publish.htm file (<CODE>CreateWebPageOnPublish</CODE>). 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.</P>
<P>I have attached the full project as a to the end of this post.</P><B>
<P>A note about Visual Studio 2008 SP1</P></B>
<P>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.</P>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/45/14/45/CreatePublishWebPage.zip" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-45-14-45/CreatePublishWebPage.zip">CreatePublishWebPage.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>What's New in Visual Studio 2008 SP1 ClickOnce Tooling</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/whats-new-in-visual-studio-2008-sp1-clickonce-tooling</link>
      <pubDate>Fri, 29 Aug 2008 18:03:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/08/29/whats-new-in-visual-studio-2008-sp1-clickonce-tooling/</guid>
      <description><![CDATA[Here is a post I've been meaning to do for a while, but avoided because there is some MSDN info on...]]></description>
      <content:encoded><![CDATA[<P>Here is a post I've been meaning to do for a while, but avoided because there is <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">some MSDN info</A> on it. But a <A class="" href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3803893&amp;SiteID=1" target=_blank mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3803893&amp;SiteID=1">recent question</A> to the forums made me think that maybe it was time to talk about things that were not addressed in the document: what's <B>really</B> 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.</P>
<P>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:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>dependency</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>dependentAssembly</FONT> <FONT color=#ff0000>dependencyType</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>preRequisite</FONT>" <FONT color=#ff0000>allowDelayedBinding</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>true</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>assemblyIdentity</FONT> <FONT color=#ff0000>name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>ClassLibrary1</FONT>" <FONT color=#ff0000>version</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>1.0.0.0</FONT>" <FONT color=#ff0000>publicKeyToken</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>F10848788BBE80F6</FONT>" <FONT color=#ff0000>language</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>neutral</FONT>" <FONT color=#ff0000>processorArchitecture</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>msil</FONT>" <FONT color=#0000ff>/&gt; 
  &lt;/</FONT><FONT color=#a31515>dependentAssembly</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>dependency</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>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.</P>
<P>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.</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>dependency</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>dependentAssembly</FONT> <FONT color=#ff0000>dependencyType</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>preRequisite</FONT>" <FONT color=#ff0000>allowDelayedBinding</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>true</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>assemblyIdentity</FONT> <FONT color=#ff0000>name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>Microsoft.Windows.CommonLanguageRuntime</FONT>" <FONT color=#ff0000>version</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>2.0.50727.0</FONT>" <FONT color=#0000ff>/&gt; 
  &lt;/</FONT><FONT color=#a31515>dependentAssembly</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>dependency</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>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.).</P>
<P>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". 
<P>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:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>dependentAssembly</FONT> <FONT color=#ff0000>dependencyType</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>preRequisite</FONT>" <FONT color=#ff0000>allowDelayedBinding</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>true</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>assemblyIdentity</FONT> <FONT color=#ff0000>name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>WindowsBase</FONT>" <FONT color=#ff0000>version</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>3.0.0.0</FONT>" <FONT color=#ff0000>publicKeyToken</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>31bf3856ad364e35</FONT>" <FONT color=#ff0000>language</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>neutral</FONT>" <FONT color=#ff0000>processorArchitecture</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>msil</FONT>" <FONT color=#0000ff>/&gt; 
&lt;/</FONT><FONT color=#a31515>dependentAssembly</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>Targeting the 3.5 framework used the "System.Core" sentinel:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>dependentAssembly</FONT> <FONT color=#ff0000>dependencyType</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>preRequisite</FONT>" <FONT color=#ff0000>allowDelayedBinding</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>true</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>assemblyIdentity</FONT> <FONT color=#ff0000>name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>System.Core</FONT>" <FONT color=#ff0000>version</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>3.5.0.0</FONT>" <FONT color=#ff0000>publicKeyToken</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>b77a5c561934e089</FONT>" <FONT color=#ff0000>language</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>neutral</FONT>" <FONT color=#ff0000>processorArchitecture</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>msil</FONT>" <FONT color=#0000ff>/&gt; 
&lt;/</FONT><FONT color=#a31515>dependentAssembly</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>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.</P>
<P>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.</P>
<P>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.</P>
<P>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:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>dependentAssembly</FONT> <FONT color=#ff0000>dependencyType</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>preRequisite</FONT>" <FONT color=#ff0000>allowDelayedBinding</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>true</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>assemblyIdentity</FONT> <FONT color=#ff0000>name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>System.Data.Entity</FONT>" <FONT color=#ff0000>version</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>3.5.0.0</FONT>" <FONT color=#ff0000>publicKeyToken</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>b77a5c561934e089</FONT>" <FONT color=#ff0000>language</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>neutral</FONT>" <FONT color=#ff0000>processorArchitecture</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>msil</FONT>" <FONT color=#0000ff>/&gt; 
&lt;/</FONT><FONT color=#a31515>dependentAssembly</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>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: </P>
<UL>
<LI><B>File Associations</B>: <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">I already wrote</A> about this, but we added UI support for file associations.</LI>
<LI><B>Exclude deployment provider</B>: 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.</LI></UL>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: 
<UL>
<LI><B>Suite Name</B>: 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.</LI>
<LI><B>Error URL</B>: Specifies the <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">web page</A> 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: 
<OL>
<LI>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)</LI>
<LI>Including the application identity for the failed installation</LI></OL></LI>
<LI><B>Create desktop shortcut</B>: 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.</LI>
<LI><B>Optional hashing</B>: 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.</LI>
<LI><B>Optional Signing</B>: 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).</LI></UL>
<P>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.</P>
<P>While the next set of features weren't added by the ClickOnce tooling team, they do affect ClickOnce published applications:</P>
<UL>
<LI><B>.NET Framework Client Profile</B>: Publishing your <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">Client Profile</A> 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.</LI>
<LI><B>Additional Bootstrapper Packages</B>: 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.</LI></UL>Finally, some high-profile bug fixes were done: 
<UL>
<LI><B>Publishing WPF applications</B>: In VS 2008, <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">strange errors</A> may crop up when publishing a WPF application: "...g.i.cs file can not be found".</LI>
<LI><B>Update to publish.htm</B>: 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</LI>
<LI><B>XML Serializer assemblies are now published with the application</B>: I wrote a <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">blog post</A> about this one, too. No need to use this work-around.</LI></UL>
<P>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 <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">hack</A> 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.</P>]]></content:encoded>
    </item>
    <item>
      <title>How To: Publish Output Groups from Other Projects in a ClickOnce Project</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/how-to-publish-output-groups-from-other-projects-in-a-clickonce-project</link>
      <pubDate>Thu, 31 Jul 2008 16:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/07/31/how-to-publish-output-groups-from-other-projects-in-a-clickonce-project/</guid>
      <description><![CDATA[In addition to output from a "compile", projects are capable of creating other outputs. Setup...]]></description>
      <content:encoded><![CDATA[<P>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:</P><PRE><FONT color=#0000ff>Sub</FONT> ListAll() 
    <FONT color=#0000ff>For</FONT> <FONT color=#0000ff>Each</FONT> proj <FONT color=#0000ff>As</FONT> Project <FONT color=#0000ff>In</FONT> DTE.Solution.Projects 
        <FONT color=#0000ff>Dim</FONT> groupInfo <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>New</FONT> StringBuilder() 
        <FONT color=#0000ff>If</FONT> proj.ConfigurationManager <FONT color=#0000ff>IsNot</FONT> <FONT color=#0000ff>Nothing</FONT> <FONT color=#0000ff>Then</FONT> 
            <FONT color=#0000ff>For</FONT> <FONT color=#0000ff>Each</FONT> group <FONT color=#0000ff>As</FONT> OutputGroup <FONT color=#0000ff>In</FONT> proj.ConfigurationManager.ActiveConfiguration.OutputGroups 
                groupInfo.AppendLine(<FONT color=#0000ff>String</FONT>.Format(<FONT color=#a31515>"{0}: {1} ({2})"</FONT>, group.CanonicalName, group.DisplayName, group.FileCount)) 
            <FONT color=#0000ff>Next</FONT> 
            MsgBox(groupInfo.ToString(), MsgBoxStyle.OkOnly, proj.Name) 
        <FONT color=#0000ff>End</FONT> <FONT color=#0000ff>If</FONT> 
    <FONT color=#0000ff>Next</FONT> 
<FONT color=#0000ff>End</FONT> <FONT color=#0000ff>Sub</FONT>
</PRE>
<P>The results for a very basic Winform Application is shown below:</P>
<P><IMG title="Project Output Groups" style="WIDTH: 249px; HEIGHT: 185px" height=185 alt="Project Output Groups" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/08/79/47/50/OutputGroups.PNG" original-url="http://blogs.msdn.com/photos/mwade/images/8794750/original.aspx" width=249 mce_src="http://blogs.msdn.com/photos/mwade/images/8794750/original.aspx"></P>
<P>It is a design <STRIKE>limitation</STRIKE> 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 <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">last month</A>&nbsp;and have a ClickOnce project publish output from other projects. </P>
<P>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:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>Target</FONT> 
            <FONT color=#ff0000>Name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>ContentFilesProjectOutputGroup</FONT>" 
            <FONT color=#ff0000>Outputs</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(ContentFilesProjectOutputGroupOutput)</FONT>" 
            <FONT color=#ff0000>DependsOnTargets</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(ContentFilesProjectOutputGroupDependsOn)</FONT>"<FONT color=#0000ff>&gt; 
 
    &lt;!--</FONT> <FONT color=#008000>Convert items into final items; this way we can get the full path for each item.</FONT> <FONT color=#0000ff>--&gt; 
    &lt;</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#a31515>ContentFilesProjectOutputGroupOutput</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(ContentWithTargetPath-&gt;'%(FullPath)')</FONT>"<FONT color=#0000ff>/&gt; 
    &lt;/</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>Target</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>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 <B>this</B> 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 <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">MSBuild task</A>.</P>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: <PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishPOG</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>..\\ClassLibrary1\\ClassLibrary1.vbproj</FONT>"<FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>false<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#a31515>OutputGroup</FONT><FONT color=#0000ff>&gt;</FONT>DebugSymbolsProjectOutputGroup<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>OutputGroup</FONT><FONT color=#0000ff>&gt; 
    &lt;/</FONT><FONT color=#a31515>PublishPOG</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishPOG</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>..\\ClassLibrary2\\ClassLibrary2.vbproj</FONT>"<FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>false<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#a31515>OutputGroup</FONT><FONT color=#0000ff>&gt;</FONT>ContentFilesProjectOutputGroup<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>OutputGroup</FONT><FONT color=#0000ff>&gt; 
    &lt;/</FONT><FONT color=#a31515>PublishPOG</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
&lt;</FONT><FONT color=#a31515>Target</FONT> <FONT color=#ff0000>Name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>BeforePublish</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Touch</FONT> <FONT color=#ff0000>Files</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(IntermediateAssembly)</FONT>" <FONT color=#0000ff>/&gt; 
    &lt;</FONT><FONT color=#a31515>MSBuild</FONT> <FONT color=#ff0000>Projects</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>%(PublishPOG.Identity)</FONT>"  <FONT color=#ff0000>Targets</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>%(OutputGroup)</FONT>"<FONT color=#0000ff>&gt; 
        &lt;</FONT><FONT color=#a31515>Output</FONT> <FONT color=#ff0000>TaskParameter</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>TargetOutputs</FONT>"  <FONT color=#ff0000>ItemName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>_DeploymentManifestFiles</FONT>" <FONT color=#0000ff>/&gt; 
    &lt;/</FONT><FONT color=#a31515>MSBuild</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>Target</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>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:</P>
<CENTER>
<TABLE class="" border=1>
<TBODY>
<TR>
<TD class=""><B>Output Type</B></TD>
<TD class=""><B>MSBuild Target Name</B></TD></TR>
<TR>
<TD class="">Content Files</TD>
<TD class="">ContentFilesProjectOutputGroup</TD></TR>
<TR>
<TD class="">Source Files</TD>
<TD class="">SourceFilesProjectOutputGroup</TD></TR>
<TR>
<TD class="">Debug Symbols</TD>
<TD class="">DebugSymbolsProjectOutputGroup</TD></TR>
<TR>
<TD class="">Documentation Files</TD>
<TD class="">DocumentationProjectOutputGroup</TD></TR>
<TR>
<TD class="">Localized resources</TD>
<TD class="">SatelliteDllsProjectOutputGroup</TD></TR>
<TR>
<TD class="">Serialization assemblies</TD>
<TD class="">SGenFilesOutputGroup</TD></TR>
<TR>
<TD class="">Primary output</TD>
<TD class="">BuiltProjectOutputGroup</TD></TR></TBODY></TABLE></CENTER>
<P>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 <CODE>_DeploymentManifestDependencies</CODE> item instead of <CODE>_DeploymentManifestFiles</CODE>.</P>
<P>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.</P>]]></content:encoded>
    </item>
    <item>
      <title>How To: Include XmlSerializers in your ClickOnce Application</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/how-to-include-xmlserializers-in-your-clickonce-application</link>
      <pubDate>Tue, 01 Jul 2008 01:23:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/07/01/how-to-include-xmlserializers-in-your-clickonce-application/</guid>
      <description><![CDATA[Have you ever noticed that when your application has a web reference, and you go to publish that web...]]></description>
      <content:encoded><![CDATA[<P>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:</P>
<UL>
<LI>Expose the web service methods through a partner Class Library, and take a reference on that Class Library</LI>
<LI>Make some modifications to Microsoft.Common.targets</LI></UL>
<P>In fact there is an easier way, which is similar to my <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">last blog post</A>. By adding the following information to your project file, the XmlSerializers assembly will start getting published with your application:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>Target</FONT> <FONT color=#ff0000>Name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>BeforePublish</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>CreateItem</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>%(SerializationAssembly.FullPath)</FONT>" <FONT color=#ff0000>Condition</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>'%(Extension)' == '.dll'</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Output</FONT> <FONT color=#ff0000>TaskParameter</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>Include</FONT>" <FONT color=#ff0000>ItemName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>_SGenDllsRelatedToCurrentDll</FONT>" <FONT color=#0000ff>/&gt; 
  &lt;/</FONT><FONT color=#a31515>CreateItem</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>Target</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>Once again, <CODE>BeforePublish</CODE> is pre-populating some items to include some information for the ClickOnce manifest generation. In this case, the <CODE>_SGenDllsRelatedToCurrentDll</CODE> items are used by the <CODE>ResolveManifestFiles</CODE> task to figure out what should be published. The definition of <CODE>SGenDllsRelatedToCurrentDll</CODE> 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. </P>
<P>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 <CODE>GenerateApplicationManifest</CODE> 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 <CODE>SerializationAssembly</CODE> in the <CODE>_SGenDllsRelatedToCurrentDll</CODE> items.</P>]]></content:encoded>
    </item>
    <item>
      <title>How To: Publish Files Which are not in the Project</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/how-to-publish-files-which-are-not-in-the-project</link>
      <pubDate>Sun, 29 Jun 2008 23:23:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/06/29/how-to-publish-files-which-are-not-in-the-project/</guid>
      <description><![CDATA[Every one in a while on our ClickOnce forums, we are asked how to publish files that aren't part of...]]></description>
      <content:encoded><![CDATA[<P>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 <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">as a link</A>; that helps a little, but you still have to add all of the files you want to publish into the project.</P>
<P>This wouldn't be an issue if the ClickOnce project were able to deal with Project Output Groups like a <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">setup project can</A>. 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.</P>
<P>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:</P>
<P><IMG title="Application Files Dialog" style="WIDTH: 600px; HEIGHT: 440px" height=440 alt="Application Files Dialog" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/08/66/98/99/ApplicationFilesDialog.PNG" original-url="http://blogs.msdn.com/photos/mwade/images/8669899/original.aspx" width=600 mce_src="http://blogs.msdn.com/photos/mwade/images/8669899/original.aspx"></P>
<P>Viewing the contents of the project file, we see this:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>ClassLibrary1</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt;</FONT>Include<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt;</FONT>Assembly<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>PublishFile</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>ClassLibrary2</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt;</FONT>Prerequisite<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt;</FONT>Assembly<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>PublishFile</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>NewFolder1\\TextFile2.txt</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt;</FONT>Foo<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt;</FONT>Auto<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt;</FONT>File<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>PublishFile</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>NewFolder1\\TextFile3.txt</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt;</FONT>Exclude<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt;</FONT>File<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>PublishFile</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>NewFolder1\\TextFile4.txt</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt;</FONT>Foo<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt;</FONT>DataFile<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt;</FONT>File<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>PublishFile</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>PublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>NewFolder1\\TextFileLink.txt</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>Group</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt;</FONT>Include<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>PublishState</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt;&lt;/</FONT><FONT color=#a31515>TargetPath</FONT><FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt;</FONT>File<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>FileType</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>PublishFile</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>All sorts of observations can be made:</P>
<UL>
<LI>Application File items are stored as Items with name "<CODE>PublishFile</CODE>"</LI>
<LI>The <CODE>Include</CODE> value is the name of the file in the application files dialog</LI>
<LI>If a metadata value is in the default state, it is generally left blank</LI>
<LI>If the entire item is in a default state, there is no entry for it in the project file (see TextFile1.txt for example)</LI>
<LI>There are 5 different metadata values for the <CODE>PublishFile</CODE> item</LI>
<OL>
<LI><CODE>Visible</CODE>, 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)</LI>
<LI><CODE>Group</CODE>, which corresponds to the Download Group in the application files dialog</LI>
<LI><CODE>PublishState</CODE>, which corresponds to how the file is distributed. There appear to be 5 different values</LI>
<UL>
<LI><CODE>(Auto)</CODE>: The file is in its default state</LI>
<LI><CODE>Include</CODE>: The file will be published with the project</LI>
<LI><CODE>Exclude</CODE>: The file will NOT be published with the project</LI>
<LI><CODE>DataFile</CODE>: The file will be published as a data file</LI>
<LI><CODE>Prerequisite</CODE>: The assembly will not be published with the application, but will be written into the manifest as a prerequisite</LI></UL>
<LI><CODE>TargetPath</CODE>, 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)</LI>
<LI><CODE>FileType</CODE>, which describes what kind of file this is</LI>
<UL>
<LI><CODE>Assembly</CODE></LI>
<LI><CODE>File</CODE></LI></UL></OL></UL>
<P>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 <CODE>@(PublishFile)</CODE>, we see the following entry:</P><PRE><FONT color=#0000ff>&lt;!--</FONT> <FONT color=#008000>Create list of items for manifest generation</FONT> <FONT color=#0000ff>--&gt; 
&lt;</FONT><FONT color=#a31515>ResolveManifestFiles</FONT> 
                <FONT color=#ff0000>EntryPoint</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(_DeploymentManifestEntryPoint)</FONT>" 
                <FONT color=#ff0000>ExtraFiles</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(_DebugSymbolsIntermediatePath);$(IntermediateOutputPath)$(TargetName).xml;@(_ReferenceRelatedPaths)</FONT>" 
                <FONT color=#ff0000>Files</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(ContentWithTargetPath);@(_DeploymentManifestIconFile);@(AppConfigWithTargetPath)</FONT>" 
                <FONT color=#ff0000>ManagedAssemblies</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(_DeploymentReferencePaths);@(ReferenceDependencyPaths);@(_SGenDllsRelatedToCurrentDll)</FONT>" 
                <FONT color=#ff0000>NativeAssemblies</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(NativeReferenceFile);@(_DeploymentNativePrerequisite)</FONT>" 
                <FONT color=#ff0000>PublishFiles</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(PublishFile)</FONT>" 
                <FONT color=#ff0000>SatelliteAssemblies</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(IntermediateSatelliteAssembliesWithTargetPath);@(ReferenceSatellitePaths)</FONT>" 
                <FONT color=#ff0000>TargetCulture</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>$(TargetCulture)</FONT>"<FONT color=#0000ff>&gt; 
 
    &lt;</FONT><FONT color=#a31515>Output</FONT> <FONT color=#ff0000>TaskParameter</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>OutputAssemblies</FONT>"  <FONT color=#ff0000>ItemName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>_DeploymentManifestDependencies</FONT>"<FONT color=#0000ff>/&gt; 
    &lt;</FONT><FONT color=#a31515>Output</FONT> <FONT color=#ff0000>TaskParameter</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>OutputFiles</FONT>"  <FONT color=#ff0000>ItemName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>_DeploymentManifestFiles</FONT>"<FONT color=#0000ff>/&gt; 
 
&lt;/</FONT><FONT color=#a31515>ResolveManifestFiles</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>This <CODE><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">ResolveManifestFiles</A></CODE> task takes all sorts of information (including <CODE>PublishFile</CODE> items). It returns the <CODE>OutputAssemblies</CODE> and <CODE>OutputFiles</CODE> as <CODE>_DeploymentManifestDependencies</CODE> and <CODE>_DeploymentManifestFiles</CODE> items, respectively. These items are then used by the <CODE>GenerateApplicationManifest</CODE> and a pair of <CODE>Copy</CODE> tasks within the <CODE>_CopyFilesToPublishFolder</CODE> 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.</P>
<P>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 <CODE>_DeploymentManifestFiles</CODE>:</P>
<UL>
<LI><CODE>Group</CODE></LI>
<LI><CODE>TargetPath</CODE></LI>
<LI><CODE>IsDataFile</CODE></LI></UL>
<P>It's a similar group to what was written for <CODE>PublishFile</CODE> items. It appears that (for files) <CODE>PublishState</CODE> was used mapped to <CODE>IsDataFile</CODE> by the <CODE>ResolveManifestFiles</CODE> task. The <CODE>FileType</CODE> metadata was used used to break all <CODE>PublishFile</CODE> items into the assemblies and files group.</P>
<P>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:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>Target</FONT> <FONT color=#ff0000>Name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>AfterPublish</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>Message</FONT> <FONT color=#ff0000>Text</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>_DeploymentManifestFiles (Identity=%(_DeploymentManifestFiles.Identity))</FONT><FONT color=#ff0000>
</FONT><FONT color=#0000ff>\tab Group=%(_DeploymentManifestFiles.Group)</FONT><FONT color=#ff0000>
</FONT><FONT color=#0000ff>\tab TargetPath=%(_DeploymentManifestFiles.TargetPath)</FONT><FONT color=#ff0000>
</FONT><FONT color=#0000ff>\tab IsDataFile=%(_DeploymentManifestFiles.IsDataFile)</FONT>" <FONT color=#0000ff>/&gt; 
&lt;/</FONT><FONT color=#a31515>Target</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>Project</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>After publishing, the output window shows (amongst other things):</P><PRE>_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
</PRE>
<P>So to add additional files to our output, we need only figure out how to generate new <CODE>_DeploymentManifestFiles</CODE> items. It turns out this is easy enough. Consider the following piece of information written into the project file:</P><PRE><FONT color=#0000ff>&lt;</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>AdditionalPublishFile</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>C:\\Documents and Settings\\mwade\\My Documents\\My Pictures\\*.jpg</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt;</FONT>False<FONT color=#0000ff>&lt;/</FONT><FONT color=#a31515>Visible</FONT><FONT color=#0000ff>&gt; 
  &lt;/</FONT><FONT color=#a31515>AdditionalPublishFile</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>ItemGroup</FONT><FONT color=#0000ff>&gt; 
&lt;</FONT><FONT color=#a31515>Target</FONT> <FONT color=#ff0000>Name</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>BeforePublish</FONT>"<FONT color=#0000ff>&gt; 
  &lt;</FONT><FONT color=#a31515>Touch</FONT> <FONT color=#ff0000>Files</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(IntermediateAssembly)</FONT>" <FONT color=#0000ff>/&gt; 
  &lt;</FONT><FONT color=#a31515>CreateItem</FONT> <FONT color=#ff0000>Include</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>@(AdditionalPublishFile)</FONT>" <FONT color=#ff0000>AdditionalMetadata</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>TargetPath=%(FileName)%(Extension);IsDataFile=false</FONT>"<FONT color=#0000ff>&gt; 
    &lt;</FONT><FONT color=#a31515>Output</FONT> <FONT color=#ff0000>TaskParameter</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>Include</FONT>" <FONT color=#ff0000>ItemName</FONT><FONT color=#0000ff>=</FONT>"<FONT color=#0000ff>_DeploymentManifestFiles</FONT>" <FONT color=#0000ff>/&gt; 
  &lt;/</FONT><FONT color=#a31515>CreateItem</FONT><FONT color=#0000ff>&gt; 
&lt;/</FONT><FONT color=#a31515>Target</FONT><FONT color=#0000ff>&gt;</FONT>
</PRE>
<P>These statements take all of the jpg files in my My Pictures directory, stores each item in a <CODE>AdditionalPublishFile</CODE>. Then as part of <CODE>BeforePublish</CODE> target, the <CODE>PublishDirectoryFile</CODE> are used (via the <CODE>CreateItem</CODE> task) to pre-populate the <CODE>_DeploymentManifestFiles</CODE> items. The <CODE>CreateItem</CODE> task sets the necessary metadata for <CODE>_DeploymentManifestFiles</CODE>: <CODE>TargetPath</CODE>, <CODE>Group</CODE>, and <CODE>IsDataFile</CODE>. The <CODE><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">Touch</A></CODE> task is used to make sure that <CODE>GenerateApplicationManifest</CODE> task is re-run as part of the publish process. <CODE>Touch</CODE> modifies the write time of the primary executable. This file is an input to the <CODE>GenerateApplicationManifest</CODE> 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.</P>
<P>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.</P>
<P>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.</P><I>Update 7/2/2008: Added information regarding the <CODE>Touch</CODE> task.</I>]]></content:encoded>
    </item>
    <item>
      <title>How To: Use Macros to Configure Publish Settings</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/how-to-use-macros-to-configure-publish-settings</link>
      <pubDate>Sat, 31 May 2008 21:06:18 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/05/31/how-to-use-macros-to-configure-publish-settings/</guid>
      <description><![CDATA[There are all sorts of publishing properties available to the Visual Studio developer. Visual Studio...]]></description>
      <content:encoded><![CDATA[<p>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.</p>  <h3>Displaying publish properties and values</h3>  <p>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:</p>  <pre class="csharpcode"><span class="kwrd">Function</span> GetPublishProperties() <span class="kwrd">As</span> EnvDTE.Properties
    <span class="kwrd">Dim</span> proj <span class="kwrd">As</span> Project = DTE.Solution.Projects.Item(1)
    <span class="kwrd">If</span> proj <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        ShowError(<span class="str">&quot;Unable to retrieve a project&quot;</span>, <span class="str">&quot;GetPublishProperties&quot;</span>)
        <span class="kwrd">Return</span> <span class="kwrd">Nothing</span>
    <span class="kwrd">End</span> <span class="kwrd">If</span>

    <span class="kwrd">Dim</span> publishProperty <span class="kwrd">As</span> EnvDTE.<span class="kwrd">Property</span> = proj.Properties.Item(<span class="str">&quot;Publish&quot;</span>)
    <span class="kwrd">If</span> publishProperty IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = <span class="kwrd">TryCast</span>(publishProperty.Value, EnvDTE.Properties)
        <span class="kwrd">Return</span> publishProperties
    <span class="kwrd">End</span> <span class="kwrd">If</span>

    ShowError(<span class="str">&quot;Unable to get publish properties of project &quot;</span> &amp; proj.Name, <span class="str">&quot;GetPublishProperties&quot;</span>)
    <span class="kwrd">Return</span> <span class="kwrd">Nothing</span>
<span class="kwrd">End</span> <span class="kwrd">Function</span>

<span class="kwrd">Sub</span> ShowError(<span class="kwrd">ByVal</span> message <span class="kwrd">As</span> <span class="kwrd">String</span>, <span class="kwrd">ByVal</span> title <span class="kwrd">As</span> <span class="kwrd">String</span>)
    MsgBox(message, MsgBoxStyle.Exclamation <span class="kwrd">Or</span> MsgBoxStyle.OkOnly, title)
<span class="kwrd">End</span> <span class="kwrd">Sub</span>

<span class="kwrd">Sub</span> ShowException(<span class="kwrd">ByVal</span> ex <span class="kwrd">As</span> Exception, <span class="kwrd">ByVal</span> methodName <span class="kwrd">As</span> <span class="kwrd">String</span>)
    <span class="kwrd">Dim</span> message <span class="kwrd">As</span> <span class="kwrd">String</span> = ex.Message
    <span class="kwrd">If</span> ex.InnerException IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        message = ex.InnerException.Message
    <span class="kwrd">End</span> <span class="kwrd">If</span>
    ShowError(message, methodName)
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">







.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; }</style>

<p><code>GetPublishProperties</code> is a function to retrieve the object which contains the publish properties. It grabs the first project in the solution, and selects the &quot;Publish&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).</p>

<p>With that as a baseline, this macro will show all of the publish properties, types, and values:</p>

<pre class="csharpcode"><span class="kwrd">Sub</span> ShowPublishProperties()
    <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = GetPublishProperties()
    <span class="kwrd">If</span> publishProperties IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        <span class="kwrd">Dim</span> sb <span class="kwrd">As</span> <span class="kwrd">New</span> System.Text.StringBuilder()
        <span class="kwrd">For</span> <span class="kwrd">Each</span> prop <span class="kwrd">As</span> EnvDTE.<span class="kwrd">Property</span> <span class="kwrd">In</span> publishProperties
            sb.Append(<span class="kwrd">String</span>.Format(<span class="str">&quot;{0} [{1}]: {2}&quot;</span>, prop.Name, prop.Value.<span class="kwrd">GetType</span>().ToString(), prop.Value.ToString()))
            sb.Append(vbCrLf)
        <span class="kwrd">Next</span>
        MsgBox(sb.ToString())
    <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">







.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; }</style>

<p>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:</p>

<pre>PublisherName [System.String]: 
OpenBrowserOnPublish [System.Boolean]: True
BootstrapperComponentsLocation [System.Int32]: 0
PublishFiles [System.__ComObject]: System.__ComObject</pre>

<p>Most of the values are <code>strings</code>, <code>ints</code>, or <code>booleans</code>. If you were to look in the project file, you would see that these values correspond to properties within the file. The exception are <code>PublishFiles</code> and <code>BootstrapperPackages</code>, 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.</code> </p>

<h3>Setting Property values</h3>

<p>Setting a value is as easy as reading a value. For example, to set the <code>PublisherName</code> property, one could write a macro like this:</p>

<pre class="csharpcode"><span class="kwrd">Sub</span> SetPublisherName()
    <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = GetPublishProperties()
    <span class="kwrd">If</span> publishProperties IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        <span class="kwrd">Dim</span> publisherNameProperty <span class="kwrd">As</span> EnvDTE.<span class="kwrd">Property</span> = publishProperties.Item(<span class="str">&quot;PublisherName&quot;</span>)
        publisherNameProperty.Value = <span class="str">&quot;Test Value&quot;</span>
    <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">



.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; }</style>

<p>Some properties perform validation when the values are set. For example, the <code>PublishUrl</code>:</p>

<pre class="csharpcode"><span class="kwrd">Sub</span> SetPublishUrl()
    <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = GetPublishProperties()
    <span class="kwrd">If</span> publishProperties IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        <span class="kwrd">Try</span>
            publishProperties.Item(<span class="str">&quot;PublishUrl&quot;</span>).Value = <span class="str">&quot;&quot;</span>
        <span class="kwrd">Catch</span> ex <span class="kwrd">As</span> Exception
            ShowException(ex, <span class="str">&quot;SetPublishUrl&quot;</span>)
        <span class="kwrd">End</span> <span class="kwrd">Try</span>
    <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">



.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; }</style>

<p>In the above example, an attempt is made to blank out the <code>PublishUrl</code> property. However, the <code>PublishUrl</code> can not be set to an empty string, as the thrown exception indicates:</p>

<pre>An empty string is not allowed for property 'Publish Location'.</pre>

<p>The thrown message uses &quot;Publish Location&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.</p>

<h3>Modifying Items</h3>

<p>There are 2 different types of <code>Items</code> exposed by the Publish</p>
Properties: <code>PublishFiles</code> and <code>BootstrapperPackages</code>. Here is a macro that does something with <code>PublishFiles</code>:</code> 

<pre class="csharpcode"><span class="kwrd">Sub</span> ListFiles()
    <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = GetPublishProperties()
    <span class="kwrd">If</span> publishProperties IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>

        <span class="kwrd">Dim</span> filesObject <span class="kwrd">As</span> <span class="kwrd">Object</span> = publishProperties.Item(<span class="str">&quot;PublishFiles&quot;</span>)
        <span class="kwrd">If</span> filesObject <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
             ShowError(<span class="str">&quot;Could not get PublishFiles object&quot;</span>, <span class="str">&quot;ListFiles&quot;</span>)
            <span class="kwrd">Return</span>
        <span class="kwrd">End</span> <span class="kwrd">If</span>

        <span class="kwrd">Try</span>
            <span class="kwrd">Dim</span> numFiles <span class="kwrd">As</span> <span class="kwrd">Integer</span>
            numFiles = filesObject.Value.Item(<span class="str">&quot;Count&quot;</span>).Value
            <span class="kwrd">Dim</span> sb <span class="kwrd">As</span> <span class="kwrd">New</span> System.Text.StringBuilder()
            <span class="kwrd">For</span> i = 0 <span class="kwrd">To</span> numFiles - 1
                <span class="rem">'display file name and publish status.</span>
                sb.AppendLine(<span class="str">&quot;File Name=&quot;</span> &amp; filesObject.<span class="kwrd">Object</span>.Item(i).Name &amp; <span class="str">&quot;, Status=&quot;</span> &amp; filesObject.<span class="kwrd">Object</span>.Item(i).PublishStatus)
            <span class="kwrd">Next</span>
            MsgBox(sb.ToString(), MsgBoxStyle.DefaultButton1, <span class="str">&quot;Application Files&quot;</span>)
        <span class="kwrd">Catch</span> ex <span class="kwrd">As</span> Exception
            ShowException(ex, <span class="str">&quot;ListFiles&quot;</span>)
        <span class="kwrd">End</span> <span class="kwrd">Try</span>
    <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">



.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; }</style>

<p>This macro relies on latebinding in doing its work: <code>filesObject</code> is declared as Object, yet it uses properties from that object. The <code>filesObject.Object</code> 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:</p>

<pre>File Name=WindowsApplication2.exe, Status=0 
File Name=WindowsApplication2.pdb, Status=0 
File Name=WindowsApplication2.xml, Status=0 </pre>

<p>The &quot;Status&quot; of the file corresponds to the Publish Status column in the Application Files dialog. 0 corresponds to the &quot;(Auto)&quot; value.</p>

<p>Accessing the bootstrapper packages is similar:</p>

<pre class="csharpcode"><span class="kwrd">Sub</span> IncludeAllPrerequisites()
    <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = GetPublishProperties()
    <span class="kwrd">Dim</span> bootstrapperPackages <span class="kwrd">As</span> <span class="kwrd">Object</span> = publishProperties.Item(<span class="str">&quot;BootstrapperPackages&quot;</span>)
    <span class="kwrd">If</span> bootstrapperPackages IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        <span class="kwrd">Dim</span> numPackages <span class="kwrd">As</span> <span class="kwrd">Integer</span> = bootstrapperPackages.Value.Item(<span class="str">&quot;Count&quot;</span>).Value
        <span class="kwrd">For</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0 <span class="kwrd">To</span> numPackages - 1
            bootstrapperPackages.<span class="kwrd">Object</span>.Item(i).Install = <span class="kwrd">True</span>
        <span class="kwrd">Next</span>
    <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span>

<span class="kwrd">Sub</span> ExcludeWindowsInstaller31()
    <span class="kwrd">Dim</span> publishProperties <span class="kwrd">As</span> EnvDTE.Properties = GetPublishProperties()
    <span class="kwrd">Dim</span> bootstrapperPackages <span class="kwrd">As</span> <span class="kwrd">Object</span> = publishProperties.Item(<span class="str">&quot;BootstrapperPackages&quot;</span>)
    <span class="kwrd">If</span> bootstrapperPackages IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
        <span class="kwrd">Dim</span> windowsInstaller31Package <span class="kwrd">As</span> <span class="kwrd">Object</span> = bootstrapperPackages.<span class="kwrd">Object</span>.Item(<span class="str">&quot;Microsoft.Windows.Installer.3.1&quot;</span>)
        <span class="kwrd">If</span> windowsInstaller31Package IsNot <span class="kwrd">Nothing</span> <span class="kwrd">Then</span>
            windowsInstaller31Package.Install = <span class="kwrd">False</span>
        <span class="kwrd">End</span> <span class="kwrd">If</span>
    <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">



.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; }</style>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. 

<h3>Publishing via a macro</h3>

<p>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:</p>

<pre class="csharpcode"><span class="kwrd">Sub</span> Publish()
    <span class="kwrd">Dim</span> proj <span class="kwrd">As</span> Project = DTE.Solution.Projects.Item(1)
    <span class="kwrd">Dim</span> sb2 <span class="kwrd">As</span> EnvDTE80.SolutionBuild2 = <span class="kwrd">CType</span>(DTE.Solution.SolutionBuild, EnvDTE80.SolutionBuild2)
    <span class="kwrd">Dim</span> config2 = <span class="kwrd">CType</span>(sb2.ActiveConfiguration, EnvDTE80.SolutionConfiguration2)
    <span class="kwrd">Dim</span> configName = <span class="kwrd">String</span>.Format(<span class="str">&quot;{0}|{1}&quot;</span>, config2.Name, config2.PlatformName)
    sb2.BuildProject(configName, proj.UniqueName, <span class="kwrd">True</span>)
    sb2.PublishProject(configName, proj.UniqueName, <span class="kwrd">True</span>)
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<style type="text/css">


.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; }</style>Ideally, the macro should verify that the build succeeded before publishing, but that has been left as an exercise for the reader. ]]></content:encoded>
    </item>
    <item>
      <title>Tool: Editing File Associations for ClickOnce Applications</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/tool-editing-file-associations-for-clickonce-applications</link>
      <pubDate>Fri, 30 May 2008 15:07:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/05/30/tool-editing-file-associations-for-clickonce-applications/</guid>
      <description><![CDATA[I apologize for taking so long between posts. I have an excuse: very busy working on Visual Studio...]]></description>
      <content:encoded><![CDATA[<P>I apologize for taking so long between posts. I have an excuse: very busy working on <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">Visual Studio 2008 SP1 (Beta)</A>. For those of you who have <A class="" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CF99C752-1391-4BC3-BABC-86BC0B9E8E5A&amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CF99C752-1391-4BC3-BABC-86BC0B9E8E5A&amp;displaylang=en">downloaded the beta</A>, 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.</P>
<P><STRONG>About the package</STRONG>: The package exposes an editor to work with file associations in the app.manifest file, as I wrote about in an <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">earlier post</A>. The editor tries to provide some error and warning feedback to cover the cases I mentioned in that post.</P>
<P><STRONG>Installing the package</STRONG>: A link is provided at the bottom of the post to install the package.</P>
<P><STRONG>Launching the editor</STRONG>: 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).</P>
<P><IMG title="Launching the editor" style="WIDTH: 304px; HEIGHT: 313px" height=313 alt="Launching the editor" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/08/56/41/85/FAPackage.png" original-url="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"></P>
<P>&nbsp;<STRONG>About the Editor</STRONG>: Here's a screen shot of the editor. I'll go into the pieces below.</P>
<P><IMG title="File Associations Editor" style="WIDTH: 634px; HEIGHT: 314px" height=314 alt="File Associations Editor" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/08/56/41/94/FAEditor.png" original-url="http://blogs.msdn.com/photos/mwade/images/8564194/original.aspx" width=634 mce_src="http://blogs.msdn.com/photos/mwade/images/8564194/original.aspx"></P>
<P mce_keep="true"><EM>Grid</EM>: 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.</P>
<P mce_keep="true"><EM>New button</EM>: Adds a new row to the grid, with some default values.</P>
<P mce_keep="true"><EM>Delete button</EM>: Deletes a row from the grid.</P>
<P mce_keep="true"><EM>Warning</EM>: Appears if some project properties would prevent the installation of the file associations from being valid.</P>
<P mce_keep="true"><STRONG>Feedback/Updates</STRONG>: 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.</P>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/08/56/41/84/FileAssociationsSetup.msi" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-08-56-41-84/FileAssociationsSetup.msi">FileAssociationsSetup.msi</a></p>]]></content:encoded>
    </item>
    <item>
      <title>How To: Add File Associations to a ClickOnce Application</title>
      <link>https://docs.microsoft.com/archive/blogs/mwade/how-to-add-file-associations-to-a-clickonce-application</link>
      <pubDate>Wed, 30 Jan 2008 15:17:00 GMT</pubDate>
      <dc:creator><![CDATA[Mike Wade - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mwade/2008/01/30/how-to-add-file-associations-to-a-clickonce-application/</guid>
      <description><![CDATA[A little-known feature that made it into .NET Framework 3.5 is the ability for a ClickOnce...]]></description>
      <content:encoded><![CDATA[<P>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 <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">MSDN information</A> 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.</P>
<H3>Adding File Associations to Your ClickOnce Manifest</H3>
<P>File associations are adding to your ClickOnce manifest by specifying the fileAssociation tag and it's 4 attributes:&nbsp; extension, description, progid, and defaultIcon. This new tag is in the clickonce.v1 namespace. So, one example looks like this:</P>
<P><BR>&lt;fileAssociation xmlns="urn:schemas-microsoft-com:clickonce.v1"<BR>&nbsp;&nbsp;&nbsp; extension=".mwade"<BR>&nbsp;&nbsp;&nbsp; description="MWadePad Document"<BR>&nbsp;&nbsp;&nbsp; progid="MWadePad.Document"<BR>&nbsp;&nbsp;&nbsp; defaultIcon="mwade.ico"<BR>/&gt; </P>
<P>A little background information about all of these:</P>
<UL>
<LI>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. </LI>
<LI>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.<IMG title="Description Tooltip" style="WIDTH: 222px; HEIGHT: 83px" height=83 alt="Description Tooltip" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/07/33/36/11/Description.PNG" original-url="http://blogs.msdn.com/photos/mwade/images/7333611/original.aspx" width=222 mce_src="http://blogs.msdn.com/photos/mwade/images/7333611/original.aspx"></LI>
<LI>progid: Helps tie the file extension to your ClickOnce application.</LI>
<LI>defaultIcon: The icon file from the ClickOnce application to use as the document icon</LI></UL>
<P>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:</P>
<P>AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0]</P>
<P>Even if the application is activated through file association, the standard ClickOnce update servicing will be applied.</P>
<H3>Adding File Associations through Visual Studio</H3>
<P>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? </P>
<P>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.</P>
<P>For example, here is what my app.manifest file looks like when adding the information from above:</P>
<P>&lt;?xml version="1.0" encoding="utf-8"?&gt;<BR>&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="<A href="http://www.w3.org/2001/XMLSchema-instance" mce_href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</A>"&gt;<BR>&nbsp; &lt;assemblyIdentity version="1.0.0.0" name="MyApplication.app" /&gt;<BR>&nbsp; &lt;trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;security&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;applicationRequestMinimum&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;defaultAssemblyRequest permissionSetReference="Custom" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/applicationRequestMinimum&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/security&gt;<BR>&nbsp; &lt;/trustInfo&gt;</P>
<P>&nbsp; &lt;fileAssociation xmlns="urn:schemas-microsoft-com:clickonce.v1"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extension=".mwade"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description="MWadePad Document"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; progid="MWadePad.Document"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; defaultIcon="mwade.ico"<BR>&nbsp; /&gt;</P>
<P>&lt;/asmv1:assembly&gt;</P>
<H3>Additional Notes</H3>
<P>There are some rules and regulations that need to be pointed out for file associations in ClickOnce:</P>
<UL>
<LI>Values must be given for all 4 xml attributes</LI>
<LI>File associations only work for pure ClickOnce applications. That means that browser-hosted applications and Office documents can't take advantage</LI>
<LI>The application must be targeting the 3.5 version of the .NET Framework</LI>
<LI>The application must be full trust</LI>
<LI>The application must be installed (not run from web)</LI>
<LI>There is a limit of 8 file associations per application</LI></UL>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/07/33/35/09/MWadePad.zip" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-07-33-35-09/MWadePad.zip">MWadePad.zip</a></p>]]></content:encoded>
    </item>
  </channel>
</rss>