February 9th, 2010

How to extend target file to include registry settings for web project package

Web project package and deployment targets files are written with extensibility in mind.  User can easily extend a property to include more functionalities in their package by using msbuild targets and properties. 

If we check the Microsoft.Web.Publishing.targets file under “%Program Files%MSBuildMicrosoftVisualStudiov10.0Web”, we can see the following, which means if file $(WebPublishPipelineProjectName).wpp.targets exists in the project directory, we’ll import it automatically when build package or publish.

  <!--***************************************************************-->
  <!--To allow the Team build to have custom setting for the Web Application project without change the project file  -->
  <!--by default, if user have a file call $(WebPublishPipelineProjectName).wpp.targets, we will import these setting in before we start  -->
  <!--***************************************************************-->
  <PropertyGroup>
    <WebPublishPipelineCustomizeTargetFile Condition="'$(WebPublishPipelineCustomizeTargetFile)'==''">$(WebPublishPipelineProjectDirectory)$(WebPublishPipelineProjectName).wpp.targets</WebPublishPipelineCustomizeTargetFile>
  </PropertyGroup>

  <Import Project="$(WebPublishPipelineCustomizeTargetFile)" Condition="Exists($(WebPublishPipelineCustomizeTargetFile))"/>

Here’s steps to create a customized target file to include some registry keys in the web package by using msdeploy’s regKey provider. (The link contains the functionality and limitation of regKey provider)

 

1. Create a file WebApplicationName.wpp.targets in the same folder as your web project (e.g. if the project file is WebApplication1.vbproj, then name the file WebApplication1.wpp.targets) with following content:

<!--********************************************************************-->
<!-- Task CollectRegKeysForPackage -->
<!-- RegKey reference: http://technet.microsoft.com/en-us/library/dd569085(WS.10).aspx -->
<!--********************************************************************-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <!--Targets get execute before this Target-->
    <OnBeforeCollectRegKeysForPackage Condition="'$(OnBeforeCollectRegKeysForPackage)'==''">
    </OnBeforeCollectRegKeysForPackage>
    <!--Targets get execute after this Target-->
    <OnAfterCollectRegKeysForPackage Condition="'$(OnAfterCollectRegKeysForPackage)'==''">
    </OnAfterCollectRegKeysForPackage>

    <CollectRegKeysForPackageDependsOn Condition="'$(CollectRegKeysForPackageDependsOn)'==''">
      $(OnBeforeCollectRegKeysForPackage);
      Build;
    </CollectRegKeysForPackageDependsOn>
  </PropertyGroup>

  <PropertyGroup>
    <IncludeRegKeyForMyProject Condition="'$(IncludeRegKeyForMyProject)'==''">False</IncludeRegKeyForMyProject>
    <MyRegKeyPath Condition="'$(MyRegKeyPath)'==''"></MyRegKeyPath>
    <AfterAddContentPathToSourceManifest Condition="'$(AfterAddContentPathToSourceManifest)'==''">
      $(AfterAddContentPathToSourceManifest);
      CollectRegKeysForPackage;
    </AfterAddContentPathToSourceManifest>
  </PropertyGroup>

  <ItemGroup>
    <MyRegkeys Include = "$(MyRegKeyPath)"/>
  </ItemGroup>

  <Target Name="CollectRegKeysForPackage"
          DependsOnTargets="$(CollectRegKeysForPackageDependsOn)"
          Condition="$(IncludeRegKeyForMyProject) AND '$(MyRegKeyPath)'!=''">

    <Message Text="Adding %(MyRegkeys.Identity)" />
    <ItemGroup>
      <MsDeploySourceManifest Include="regkey"
                                 Condition="$(IncludeRegKeyForMyProject)">
        <Path>%(MyRegkeys.Identity)</Path>
      </MsDeploySourceManifest>
    </ItemGroup>
    <CallTarget Targets="$(OnAfterCollectRegKeysForPackage)" RunEachTargetSeparately="false" />
  </Target>
</Project>

2. Package the project from command line using parameters such as the following to include multiple registry keys (seperated by ; sign) in the package.

msbuild WebApplication1.vbproj /target:package /p:IncludeRegKeyForMyProject=True;MyRegKeyPath="hkey_current_usercontrol paneldesktopwindowmetrics;hkey_current_usercontrol paneldesktopcolors"

In objdebugpackageWebApplication1.SourceManifest.xml file, you should see two regkey providers are defined:

<?xml version="1.0" encoding="utf-8"?>
<sitemanifest>
  <regkey path="hkey_current_usercontrol paneldesktopwindowmetrics" />
  <regkey path="hkey_current_usercontrol paneldesktopcolors" />
  <IisApp path="D:tempWebApplication1WebApplication1objDebugPackagePackageTmp" managedRuntimeVersion="v4.0" />
  <setAcl path="D:tempWebApplication1WebApplication1objDebugPackagePackageTmp" setAclResourceType="Directory" />
  <setAcl path="D:tempWebApplication1WebApplication1objDebugPackagePackageTmp" setAclUser="anonymousAuthenticationUser" setAclResourceType="Directory" />
</sitemanifest>

3. To proves it works, we change the hkey_current_usercontrol paneldesktopwindowmetricsMenuWidth from –285 to –284, then we deploy the package locally from command line:

WebApplication1.deploy.cmd /y

4. We see the following line which showed that the corresponding registry is updated.

Info: Updating regValue (hkey_current_usercontrol paneldesktopwindowmetricsMenuWidth).

5. Or we can import the package from IIS

image

After installation finishes, from its details tab, there are the following messages:

[2/9/2010 11:55:05 AM] Source regValue (hkey_current_usercontrol paneldesktopwindowmetricsMenuWidth) does not match destination (hkey_current_usercontrol paneldesktopwindowmetricsMenuWidth) differing in attributes (value[‘-285′,’-284′]). Update pending.
[2/9/2010 11:55:05 AM] Source regValue (hkey_current_usercontrol paneldesktopwindowmetricsMenuWidth) replaced with changed attributes (parameters) because of rule EnvironmentVariableNormalize.

[2/9/2010 11:55:05 AM] Updating regValue (hkey_current_usercontrol paneldesktopwindowmetricsMenuWidth).

 

If you simply want to hardcode the registry keys for your project and don’t want to worry about more extensions, here’s a simplified version:

<!--********************************************************************-->
<!-- Task CollectRegKeysForPackage -->
<!-- RegKey reference: http://technet.microsoft.com/en-us/library/dd569085(WS.10).aspx -->
<!--********************************************************************-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <!-- Extends the AfterAddContentPathToSourceManifest action do also collect registry keys-->
    <!-- Hard code -->
    <MyRegKeyPath Condition="'$(MyRegKeyPath)'==''">hkey_current_usercontrol paneldesktopwindowmetrics;hkey_current_usercontrol paneldesktopcolors</MyRegKeyPath>
    <AfterAddContentPathToSourceManifest Condition="'$(AfterAddContentPathToSourceManifest)'==''">
      $(AfterAddContentPathToSourceManifest);
      CollectRegKeysForPackage;
    </AfterAddContentPathToSourceManifest>
  </PropertyGroup>

  <ItemGroup>
    <MyRegkeys Include = "$(MyRegKeyPath)"/>
  </ItemGroup>
  
  <Target Name="CollectRegKeysForPackage" Condition="'$(MyRegKeyPath)'!=''">
    <Message Text="Adding %(MyRegkeys.Identity)" />
    <ItemGroup>
      <MsDeploySourceManifest Include="regkey">
        <Path>%(MyRegkeys.Identity)</Path>
      </MsDeploySourceManifest>
    </ItemGroup>
  </Target>

</Project>

Note: if you change an existing target file (this.wpp.targets).  You need to restart VS IDE to allow the target file cache to be unloaded and reloaded, in order for package/publish using the change.

Xinyang Qiu | Visual Web Devloper

0 comments

Discussion are closed.