This topic has not yet been rated - Rate this topic

Developing Applications with the Updater Application Block

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

 

Developing Applications with the Updater Application Block

Updater Application Block - Version 2.0

patterns & practices Developer Center

Microsoft Corporation

March 2005

Summary: This chapter describes how to integrate the Updater Application Block into your solution and configure it for your particular scenario. It also contains information that will help you complete each development task associated with using the application block.

The Updater Application Block is designed to use in your applications to provide updating functionality with minimum development work. However, it is also designed to be extensible so that you can customize it to use specific providers that your solution requires.

This section describes how you can use the Updater Application Block to develop applications. It includes information that will help you incorporate the application block into your solution and configure it for your particular scenario. It also contains information that will help you complete each development task associated with using the application block. This section includes the following topics:

Download and Install the Updater Application Block

Choose the Application Scenario

Create the Manifest File

Configure the Client Application

Prepare the Client Application

Add Updater Code to the Application

Download and Install the Updater Application Block

Before you can use the Updater Application Block in your applications, you must download the application block and install it on your development computer.

Note   The software requirements for the Updater Application Block are listed in the Introduction to the Updater Application Block.

Download and Install the Enterprise Library Application Blocks

The Updater Application Block is dependent on the patterns & practices Enterprise Library Cryptography Application Block. You must download and install Enterprise Library-June 2005 before installing the Updater Application Block. For more information about Enterprise Library, see http://msdn.microsoft.com/library/en-us/dnpag2/html/entlib.asp.

Download the Updater Application Block

A Windows Installer file that contains the Updater Application Block projects, source code, and documentation is available from http://www.microsoft.com/downloads/details.aspx?FamilyId=C6C09314-E222-4AF2-9395-1E0BD7060786&displaylang=en.

Install the Updater Application Block

You must run the Windows Installer file to install the Updater Application Block on your computer.

To install the Updater Application Block

  1. Open Windows Explorer and locate the downloaded Windows Installer file.
  2. Double-click ApplicationUpdater2.msi.
  3. Specify your required installation path and install the application block.

Modify the Updater Application Block to Use Enterprise Library-June 2005

The Updater Application Block needs to be modified to use Enterprise Library-June 2005. You must perform the following steps:

  1. Download Enterprise Library-June 2005.
  2. Install and compile the Enterprise Library.
  3. Open the Visual Studio Updater.sln solution file in Visual Studio .NET 2003. On the taskbar, click Start, point to Programs, point to Microsoft patterns & practices, point to Updater Application Block v2, and then click CS Application Updater Solution or VB Application Updater Solution.
  4. If the Common project is unavailable, remove the project from the solution. To do this, right-click on the Common project and select Remove. Next, right click on the Updater Solution, point to Add, and select Existing Project. Browse to the Enterprise Library-June 2005 Common project file (by default, located in C:\Program Files\Microsoft Enterprise Library June 2005\src\Common)
  5. Repeat Step 4 for the Configuration project. By default, it is located in C:\Program Files\Microsoft Enterprise Library June 2005\src\Configuration.
  6. Repeat Step 4 for the Configuration.Design project. By default, it is located in C:\Program Files\Microsoft Enterprise Library June 2005\src\Configuration\Design).
  7. Repeat Step 4 for the Security.Cryptography project. By default, it is located in C:\Program Files\Microsoft Enterprise Library June 2005\src\Security\Cryptography).
  8. Repeat Step 4 for the Security.Cryptography.Configuration.Design project. By default, it is located in C:\Program Files\Microsoft Enterprise Library June 2005\src\Security\Cryptography\Configuration\Design).
  9. In the solution explorer, expand the References folder under the ActivationProcessors project. Remove references to the following projects. To do this, right-click on the project and select Remove:
    • Common
    • Configuration
    • Security.Cryptography

    Add references to the following projects. To do this, right-click on References and select Add Reference. Click on the Projects tab, select the following projects, and click OK:

    • Microsoft.Practices.EnterpriseLibrary.Common
    • Microsoft.Practices.EnterpriseLibrary.Configuration
    • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography
  10. Repeat Step 9 for the Downloaders project. Add references to the following projects:
    • Microsoft.Practices.EnterpriseLibrary.Common
    • Microsoft.Practices.EnterpriseLibrary.Configuration
  11. Repeat Step 9 for the Updater project. Add references to the following projects:
    • Microsoft.Practices.EnterpriseLibrary.Common
    • Microsoft.Practices.EnterpriseLibrary.Configuration
    • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography
  12. Repeat Step 9 for the Updater.Configuration.Design project. Add references to the following projects:
    • Microsoft.Practices.EnterpriseLibrary.Common
    • Microsoft.Practices.EnterpriseLibrary.Configuration
    • Microsoft.Practices.EnterpriseLibrary.Configuration.Design
    • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography
    • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration.Design

Build the Solution

The installation process creates a Microsoft patterns & practices submenu on your Programs menu. On this menu, there is an Updater Application Block v2 submenu that includes options to read the documentation, to install the QuickStart demonstration applications, and to open the Updater Application Block Visual Studio .NET solutions.

To build the solution

  1. On the taskbar, click Start, point to Programs, point to Microsoft patterns & practices, point to Updater Application Block v2, and then click CS Application Updater Solution or VB Application Updater Solution.
  2. When the solution opens in Visual Studio, click Rebuild Solution on the Build menu.

Run the QuickStarts

After you install and modify the Updater Application Block to use Enterprise Library-June 2005, you should run the QuickStarts. First, you will need to perform the steps mentioned in the "Modify the Updater Application Block to Use Enterprise Library-June 2005" for each Quickstart and then you can build and run the QuickStart. You can install the QuickStart applications by using the Deploy QuickStarts option on the QuickStarts submenu. This creates the Web folders required by the QuickStart samples. You can remove the QuickStarts from your computer by using the Uninstall QuickStarts option on the QuickStarts submenu.

Choose the Application Scenario

The first step in building an application using the Updater Application Block is to decide which scenario your application fits. This decision will determine how and where you must write the updater code.

The Updater Application Block is designed to support the most common automatic update scenarios for Windows Forms clients. This section provides details of those scenarios and how to develop applications for them. It includes the following topics:

Using the Updater Application Block as an In-Process Component

Using a Stub Application to Check for Updates

Using a Windows Service to Check for Updates

Performing Partial Updates

Using the Updater Application Block as an In-Process Component

A common update requirement is for an application to check for updates while the application is running. For example, your application may check for updates at preset intervals when the application is running or when a user initiates the process from a menu or button. In this scenario, any updates are downloaded while the client application is running and can be activated either when the application is running or when the application exits. The updated version is then available when the application restarts. This solution is ideal for applications that support multiple plug-ins that are either automatically downloaded from the server or downloaded on request.

To implement this solution, you can use the WaitForApplicationExitProcessor. This processor creates a new process to run the PostApplicationExitActivationProcessor, and the WaitForApplicationExitProcessor suspends the activation of the downloaded files. The PostApplicationExitActivationProcessor assembly waits for the client application to exit and then resumes activation of the update tasks that have been stored in the updater registry using the same configuration files as the client application.

To use the Updater Application Block as an in-process component

  1. Determine the event that should trigger the update. For example, a menu item clicked by a user or continuous polling for available updates from a new thread might trigger the update.
  2. Add code to the chosen event that executes the following steps:
    1. Creates an instance of the ApplicationUpdaterManager
    2. Checks for available manifests on the server
    3. Retrieves manifest information from the server
    4. Adds event handlers for download and activation events
    5. Downloads the updates
    6. Activates the updates
    Note   For more information about writing this code, see Add Updater Code to the Application.
  3. Create a manifest file that uses at least the following activation processors:
    1. WaitForApplicationExitProcessor
    2. ApplicationDeployProcessor
    Note   For more information about creating the manifest, see Create the Manifest File.

Usage Notes

You should decide whether you want the update process to be initiated by the user or start automatically at set intervals. This decision determines where the updater code should be in the application.

If you want the application to poll for updates, you should start a new thread to handle the update process. This prevents the polling process from blocking the main application thread.

The manifest file must include the WaitForApplicationExitProcessor in case you have to replace files or assemblies that are locked by the application at run time and the ApplicationDeployProcessor to copy files or assemblies to their final destination. While the application is running, the activation process copies the downloaded files to a temporary location and you can use the WaitForApplicationProcessor to suspend activation until the client application exits. When the application exits, the processors resume and copy the downloaded files that were locked by the application to the final location. You can also include other application processors as needed by your application. The order of the processor execution is determined by the order of the task elements in the manifest file.

If the WaitForApplicationExitProcessor is specified in the manifest, any processor later in the list will not be executed until the application exits and the activation of pending tasks resumes.

QuickStart Examples

For an extended example of this scenario, see the QuickStart walkthroughs, Auto InProc QuickStart and Manual InProc QuickStart.

Using a Stub Application to Check for Updates

You can use an application launcher as a "bootstrap" or "shim" to start applications that can be updated by the Updater Application Block. This design avoids the issue of updating an application while it is running. In this scenario, updates are downloaded and activated before the client application starts or after the application shuts down.

To implement this solution, you can use the AppStart assembly that is included in the Simple AppStart QuickStart to check for updates, download updates, and activate tasks. This assembly can be configured to perform the update process either before the client application starts or after it exits. The assembly starts by confirming that only one instance of AppStart is running. This ensures that multiple launchers do not try to download and start the same updates at the same time.

To use the AppStart assembly to check for updates

  1. Add the AppStart project to your solution and set it to be the start up project.
  2. Determine whether the client application should start after the update process or run and exit before the update process starts. Then use the information in Table 3.1 to modify the settings in the appStart element of the AppStart application configuration file (App.config) to match your solution requirements.

    Table 3.1: Elements in AppStart configuration file

ElementDescription
appFolderNameFolder location that contains the client application executable file.
appExeNameName of the client application executable file.
appIDIdentifier of the client application.
updateTimeWhen the update process should be started with regard to the client application. This can be BeforeStart or AfterShutdown.
manifestUriLocation of the manifest file on the server.

  1. Create a manifest file for your application.
    Note   For more information about creating the manifest, see Create the Manifest File.

Usage Notes

You should create your application shortcuts to point to AppStart.exe. This automatically launches the client application either before or after the update process runs.

You should use the AppStart configuration file (App.config) to configure the settings for the update process. For more information about the structure of this file, see Table 3.1.

QuickStarts

For an extended example of this scenario, see the QuickStart walkthrough, Simple AppStart QuickStart.

Using a Windows Service to Check for Updates

The third common requirement is for a Windows service to check for updates for several different applications at set intervals. For example, a Windows service could check for updates every half hour that the client computer is running. In this scenario, updates that are available on the server are downloaded and activated, regardless of the user running a particular application.

To implement this solution, you must create a Windows service project and add code to the OnStart method that periodically queries the server for available updates. If updates are available, your code in this method should download and activate the updates using the information specified in the configuration files. You must also add code to the OnStop method to stop querying the server for updates.

To use a Windows service to check for updates

  1. Create a Windows service application.
  2. Add an application configuration file to the Windows Service project that includes a configuration section defining the update interval for the service and the application identifiers, manifest URIs, and application locations for each application that is to be updated.

    The following code sample shows an example structure for this configuration section.

    <configuration>
      <configSections>
        <section name="enterpriselibrary.configurationSettings" type="Microsoft.Practices.EnterpriseLibrary.Configuration.ConfigurationManagerSectionHandler..." />
        <section name="updaterSvc" type="myUpdSvc.ConfigHandler, myUpdSvc" />
      </configSections>
      <updaterSvc updateInterval="30000">
        <applications>
          <application id="{ABD7A060-9FE7-4a89-948D-333EF2B80EFD}" manifestUri="http://deployserver/applications/ABD7A060-9FE7-4a89-948D-333EF2B80EFD.xml" location="c:\program files\myCompany\myApplication" />
          <application id="{A0F146C0-3F9A-4c9c-B4ED-791F7BBA5F43}" manifestUri="http://deployserver/applications/A0F146C0-3F9A-4c9c-B4ED-791F7BBA5F43.xml" location="c:\program files\myCompany\myOtherApplication" />
        </applications>
      </updaterSvc>
      <enterpriselibrary.configurationSettings... />
    </configuration>
      
  3. Add a class that implements the IConfigurationSectionHandler interface to the project to expose the information in this configuration section to the client application code. This class is identified in the type attribute of the section element in the configuration file.
  4. Add code to the OnStart method to do the following:
    1. Create an instance of the ApplicationUpdaterManager object for each updateable application by calling the GetUpdater method and passing the application ID retrieved from the configuration file.
    2. Query the server for available updates for each updateable application passing the manifestUri retrieved from the configuration file to the GetUpdater method.
    3. Modify the Manifest.Application.Location property of each returned manifest to match the location specified in the configuration file for that application.
  5. Download and activate the updates.
    Note   For more information about writing this code, see Add Updater Code to the Application.
  6. Add code to the OnStop method to stop querying the server for updates.
  7. Create a manifest file for the application updates.
    Note   For more information about creating the manifest, see Create the Manifest File.

Usage Notes

You should decide how frequently you want your service to query the server for updates. Then you can use the updateInterval attribute in the application configuration file to define the intervals for the service to query the server for updates.

Performing Partial Updates

Although you may frequently want to update the whole client application, sometimes you may want to perform a partial update. For example, you may want to update only a small file that is used by the main assembly. The Updater Application Block provides two different ways of implementing partial updates:

Using File Hash Comparisons for Partial Updates

Using Windows Installer Packages for Partial Updates

Using File Hash Comparisons for Partial Updates

The Updater Application Block includes the ability to compare file hashes on potential download files to verify whether the versions currently on the client computer differ from the updates available on the server. This lets you minimize the number of downloaded files, therefore minimizing the overall time for the update process to occur.

To implement this solution, you must modify the files and file elements in the manifest file to include the hash comparison flag, the hash of the file on the server, and the hash provider to use. When the manifest is retrieved from the server, the hash comparison flag is checked. If this flag is set to true, the hash value retrieved from the manifest is compared with the file on the client computer and if the file has not changed, it is removed from the list of files to download in the manifest class.

You can compare file hashes in each of the three scenarios previously described.

To use file hash comparisons to download partial updates

  1. Follow the procedure listed for your chosen scenario from the previous topics.
  2. Compute hash values for the downloadable files that will be added to the server.
  3. Use the information in Table 3.2 to define the files and file elements in the manifest using the Manifest Editor tool.

    Table 3.2: Elements and attributes of the files element

ElementAttributeDescription
fileshashComparisonBoolean value that indicates whether hashes should be compared.
fileshashProviderString defining the name of the hash provider to use when computing and comparing hashes. This must match a hash provider defined in the application configuration file, EnterpriseLibrary.Security.Cryptography.config. You can create this file using the Enterprise Library Configuration Console.
filehashString defining the hash value of the available file update on the server. Used to compare with the hash value of the corresponding file on the client computer.

Note   For more information about creating the manifest, see Create the Manifest File.

The following code shows an example of the files element of a manifest file that uses hash comparisons.

<files base="http://localhost/Updater2QuickStarts/cs/AutoInproc/server/" hashComparison="Yes" hashProvider="hmac1">
  <file source="AutoInproc.exe" hash="a5aqUnlIyzu670VDJW8lSwXJdJM="/>
  <file source="AutoInproc.pdb" hash="0UOXi/+fNtBihjD9Vv8WS+1NBCo="/>
</files>
  

Usage Notes

Your client application does not have to include any additional code to use file hash comparisons. However, you must make sure that your manifest file contains the required information for the comparison to occur.

The client application must have the hashProviders configured in order to perform the hash comparison tasks.

QuickStarts

For an extended example of this scenario, see the QuickStart walkthrough, Auto InProc QuickStart.

Using Windows Installer Packages for Partial Updates

You can use the Updater Application Block to download and run Windows Installer package (.msi) files and Windows Installer update (.msp) files. This lets you install, update, reinstall, and remove applications from client computers by adding a manifest and Windows Installer files on a central server. You can implement partial updates by creating a Windows Installer patch (.msp file) that includes only the changed files of an application. This minimizes the download size of the update and can preserve user customization of the application through the upgrade. Windows Installer has simpler customization and post-download processing than custom activation processors. For example, you can include complex registration procedures within a Windows Installer package.

To implement this solution, you can use the MSIProcessor activation processor. It runs a Windows Installer package using the configuration specified in the manifest. You can implement a partial update using Windows Installer files in each of the three scenarios previously described.

To use Windows Installer packages to download partial updates

  1. Follow the procedure listed for your chosen scenario from the previous topics.
  2. Use the information in Table 3.3 to add a task element to the manifest that runs the MSIProcessor.

    Table 3.3: Elements and attributes of the task element for the MSIProcessor

    Element / AttributeDescription
    installTypeType of installation process that should be executed. This can be Install, Patch, or Remove.
    packagePathRelative path from the manifest to the package.
    propertyValuesCommand line property values for the package. For example, setting the INSTALLLEVEL property will configure which features are set to "ON" for installation by default.

    For more information about Windows Installer properties, see Properties.

    uiLevelType of user interface interaction to be used. This can be one of the following values:

    msiUILevelNoChange

    msiUILevelDefault

    msiUILevelNone

    msiUILevelBasic

    msiUILevelReduced

    msiUILevelFull

    msiUILevelHideCancel

    msiUILevelProgressOnly

    msiUILevelEndDialog

    For more information about Windows Installer user interface levels, see Installer.UILevel.

Note   For more information about creating the manifest, see Create the Manifest File.

The following code shows an example of the activation element of a manifest file that uses the MSIProcessor.

<activation>
    <tasks>
        <task type = "Microsoft.ApplicationBlocks.Updater.ActivationProcessors.MSIProcessor, Microsoft.ApplicationBlocks.Updater.ActivationProcessors" name="MSIProcessor">
            <config>
                <installType>Install</installType>
                <uiLevel>msiUILevelProgressOnly</msi:uiLevel>
                <packagePath>SimpleApplicationSetup.msi</msi:packagePath>
                <propertyValues>ACTION=INSTALL</msi:propertyValues>
            </config>
        </task>
    </tasks>
</activation>
  

Usage Notes

The MSIProcessor uses the information from the manifest file to determine whether an install, update, or remove action should be executed. It then uses the WindowsInstaller.Installer class to perform the appropriate action.

Your client application does not have to include any additional code to use this processor; however, you must make sure that your manifest file contains the required information for the processor to run.

QuickStarts

For an extended example of this scenario, see the QuickStart walkthrough, MSI QuickStart.

Create the Manifest File

The manifest file contains information that the Updater Application Block uses to configure the update process. It contains the following information:

  • The application the manifest belongs to
  • The files to download
  • The downloader implementation to use
  • The post-download activators to use
  • The other manifests to include

You can generate a manifest file using the manifest editor that is included in the Updater Application Block download.

To create a manifest file using the Manifest Editor

  1. Open the Manifest Editor solution:
    1. On the taskbar, click Start, point to Programs, point to Microsoft patterns & practices, point to Updater Application Block v2, and then click CS ManifestEditorTool Solution.
    2. Run the application.
  2. On the Manifest Properties tab, enter the manifest and included manifests information, as shown in Figure 3.1:
    • You can click Generate to automatically generate a GUID for the manifest.
    • You can use the Included Manifests section to include additional manifests within this manifest. When the application queries the server for updates, if the primary manifest contains any included manifests an array of all the manifests will created for processing.

    Ff648668.f03uab01(en-us,PandP.10).gif

    Figure 3.1. Manifest Properties

  3. Click the Downloader tab and enter the downloader name, as shown in Figure 3.2.

    Ff648668.f03uab02(en-us,PandP.10).gif

    Figure 3.2. Downloader

  4. Click the Application Properties tab, and then enter the application information, as described in Table 3.4 and shown in Figure 3.3.

    Table 3.4: Application Properties descriptions

    NameDescription
    Application IdA unique identifier for the application.
    LocationInformation about the path on the client computer where the updates should be copied.

    This can be verified or changed as required by the executing assembly.

    FileThe file to use as the entry point for the application.
    ParametersAny parameters required by the entry point application.
    Base PathThe location on the server where the updates are located.
    Use hashingDefines whether to use hashing comparisons for partial updates.

    Selecting this check box prompts you to specify the cryptography configuration file to use. The hash providers from this file then populate the drop down list and you can select the provider to use.

    Source FolderThe folder that contains the updates.
    FilesThe list of update files.

    Files with selected check boxes are marked as transient in the manifest and are not deployed when using the ApplicationDeployProcessor.

    Ff648668.f03uab03(en-us,PandP.10).gif

    Figure 3.3. Application Properties

    Note   By default, Internet Information Server (IIS) version 6.0 prohibits all unknown CGI extensions from being downloaded. You must enable this setting if you want .exe and .dll files to be downloaded from the Web server.
    You must also add .pdb and .msp to the list of registered MIME to ensure that they are not filtered by the server.
    For more information about configuring IIS 6.0, see Configure the QuickStarts.
  5. Click the Activation Process tab, and then add each activation processor that you want to run, as shown in Figure 3.4. When you add a configurable processor, a custom configuration dialog box is displayed that you can use to specify the configurable settings. For example, when adding an MSIProcessor, you can specify the Install type, UI Level, Product code, Property values, and Property path. You can also open this dialog box by selecting the appropriate processor and clicking Configure.

    Ff648668.f03uab04(en-us,PandP.10).gif

    Figure 3.4. Activation Process

  6. Click Validate to ensure information that you entered is valid.
  7. Click View to review the manifest that will be generated.
  8. Click Save and save the manifest to the required location.

Sample Output

The following code shows an example of a manifest created using the Manifest Editor.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" manifestId="(ec7f1573-67f2-452d-9e44-27d32b06638a)" mandatory="Yes" xmlns="urn:schemas-microsoft-com:PAG:updater-application-block:v2:manifest">
  <description>Manifest for MyApp</description>
  <application applicationId="(54a97e8d-2430-4a99-8f3c-7284f916d685)">
    <entryPoint file="MyApp.exe" />
    <location>.\..\..</location>
  </application>
  <files base="http://server1/MyApp/Updates" hashComparison="No">
    <file source="Update.txt" transient="No" />
  </files>
  <downloader name="BITSDownloader" />
  <activation>
    <tasks>
      <task type="Microsoft.ApplicationBlocks.Updater.ActivationProcessors.ApplicationDeployProcessor, Microsoft.ApplicationBlocks.Updater.ActivationProcessors" name="ApplicationDeployProcessor" />
    </tasks>
  </activation>
  <includedManifests>
    <manifest location="Manifest2.xml" manifestId="(1cb35e4c-33ed-428c-9e50-6d2897f1f262)" />
  </includedManifests>
</manifest>
  

Securing the Manifest File

The manifest is downloaded from the server using HTTP, which is not a secure download technology. This causes a potential threat of the manifest file being tampered with during transmission and incorrect updates being applied to client computers.

There are two countermeasures you can use to help protect against this threat:

  • Use HTTPS to prevent tampering during transmission.
  • Modify the ManifestManager class to support digitally signed manifests.

Configure the Client Application

The Updater Application Block uses information in configuration files to determine the information that is required at run time. You can use the Enterprise Library Configuration Console to generate the configuration files required by the Updater Application Block.

This tool generates three configuration files for the Updater Application Block:

  • App.config. This file contains metadata for the application block.
  • Updaterconfiguration.config. This file contains the settings used by the application block to locate the manifest on the server, to authenticate against that server, and to identify the required downloader.
  • securityCryptographyConfiguration.config. This file contains the settings used by the application block to locate the hash provider on the client. The application block uses the hash provider to validate downloaded files during a partial update.
    Note   This file is also used on the server when creating the manifest.

For details about Enterprise Library Security Application Block and Enterprise Library Cryptography Application Block configuration, see the Enterprise Library documentation.

To create the configuration files using the Enterprise Library Configuration Console

  1. On the taskbar, click Start, point to Programs, point to Microsoft patterns & practices, point to Updater Application Block v2, and then click Enterprise Library Configuration Tool.
  2. On the File menu, click New Application.
  3. Enter the following details to the Application1 node, as shown in Figure 3.5:
    1. ConfigurationFile–path and file name for App.config
    2. Name–the name of your application

    Ff648668.f03uab05(en-us,PandP.10).gif

    Figure 3.5. Application node

  4. On the Action menu, point to New, and then click Updater Application Block Configuration.
  5. In the left pane, click Updater Application Block. Enter the following details to the Updater Application Block node, as shown in Figure 3.6:
    1. ApplicationId–the application identifier as specified in the manifest
    2. BasePath–the path on the client computer where the updates should be downloaded
    3. ManifestUri–the URI to the manifest

    Ff648668.f03uab06(en-us,PandP.10).gif

    Figure 3.6. Updater Application Block node

  6. On the Action menu, point to New, and then click Downloaders.
  7. On the Action menu, point to New, and then click BITS Downloader.
  8. Enter the authentication information for your server, as shown in Figure 3.7.

    Ff648668.f03uab07(en-us,PandP.10).gif

    Figure 3.7. Downloaders node

  9. On the File menu, click Save Application. The configuration files will be saved in the path specified in the ConfigurationFile setting.
Note   There are other elements that can be included in the application configuration files, for example, the service and manifestManager elements. For more information about the other elements, see Configuration Design.

Sample Output

The following code shows an example of the configuration files, App.config and Updaterconfiguration.config, created using the Enterprise Library Configuration Console.

App.config

<configuration>
  <configSections>
    <section name="enterpriselibrary.configurationSettings" type="Microsoft.Practices.EnterpriseLibrary.Configuration.ConfigurationManagerSectionHandler, Microsoft.Practices.EnterpriseLibrary.Configuration" />
  </configSections>
  <enterpriselibrary.configurationSettings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" applicationName="MyApp" xmlns="http://www.microsoft.com/practices/enterpriselibrary/08-31-2004/configuration">
  <configurationSections>
    <configurationSection xsi:type="ReadOnlyConfigurationSectionData" name="securityCryptographyConfiguration" encrypt="false">
      <storageProvider xsi:type="XmlFileStorageProviderData" name="XML File Storage Provider" path="securityCryptographyConfiguration.config" />
      <dataTransformer xsi:type="XmlSerializerTransformerData" name="Xml Serializer Transformer">
        <includeTypes />
      </dataTransformer>
    </configurationSection>
    <configurationSection xsi:type="ReadOnlyConfigurationSectionData" name="UpdaterConfiguration" encrypt="false">
      <storageProvider xsi:type="XmlFileStorageProviderData" name="XML File Storage Provider" path="UpdaterConfiguration.config" />
      <dataTransformer xsi:type="XmlSerializerTransformerData" name="Xml Serializer Transformer">
        <includeTypes>
          <includeType name="BITSDownloaderProviderData" type="Microsoft.ApplicationBlocks.Updater.Configuration.BitsDownloaderProviderData, Microsoft.ApplicationBlocks.Updater.Downloaders" />
        </includeTypes>
      </dataTransformer>
    </configurationSection>
  </configurationSections>
  <keyAlgorithmStorageProvider xsi:nil="true" />
  <includeTypes />
</enterpriselibrary.configurationSettings>
</configuration>
  

Updaterconfiguration.config

<?xml version="1.0" encoding="utf-8"?>
<UpdaterConfiguration>
  <xmlSerializerSection type="Microsoft.ApplicationBlocks.Updater.Configuration.ApplicationUpdaterSettings, Microsoft.ApplicationBlocks.Updater">
    <applicationUpdater xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" basePath="C:\Program Files\MyApp\Updates" applicationId="(54a97e8d-2430-4a99-8f3c-7284f916d685)" manifestUri="http://server1/MyApp/Manifest.xml" xmlns="urn:schemas-microsoft-com:PAG:updater-application-block:v2">
      <downloaders>
        <downloader xsi:type="BitsDownloaderProviderData" name="BITSDownloader">
         <authenticationScheme>BG_AUTH_SCHEME_NTLM</authenticationScheme>
         <targetServerType>BG_AUTH_TARGET_SERVER</targetServerType>
        </downloader>
      </downloaders>
    </applicationUpdater>
  </xmlSerializerSection>
</UpdaterConfiguration>
  

Prepare the Client Application

Before you can add to your application the code that interacts with the Updater Application Block, you must add references to your application and import the namespaces into your classes.

To add references to the application block assemblies

  1. Use the Visual Studio .NET Solution Explorer window to add references to the following components:
    1. Microsoft.ApplicationBlocks.Updater.dll

    This file is located in the Updater Application Block\Common folder of the install folder.

    You must also make sure that the client application can access the Microsoft.ApplicationBlocks.Updater.Downloader and Microsoft.ApplicationBlocks.Updater.ActivationProcessors assemblies. For example, make sure they are present in the application folder or the global assembly cache.

To import the namespaces

  1. Simplify your calls to the Updater Application Block by importing the Microsoft.ApplicationBlocks.Updater namespace into your application code. Add the following code to import this namespace.
     [C#]
    using Microsoft.ApplicationBlocks.Updater;
    
    [Visual Basic]
    Imports Microsoft.ApplicationBlocks.Updater
      

Add Updater Code to the Application

There is a core set of development tasks that you must implement in each scenario the Updater Application Block supports. The location of the code that implements these tasks in your application depends on the update scenario you have chosen. For more information about the location, see Choose the Application Scenario. The following topics provide descriptions and code examples of the core tasks:

Create an Instance of ApplicationUpdaterManager

Check for Updates

Handle Pending Updates

Download Updates

Activate Updates

Handle Progress Events

Create an Instance of the ApplicationUpdaterManager

The ApplicationUpdaterManager class is the core controller of the update process. It is a facade into the application block and controls the actions of the application block. The ApplicationUpdaterManager implements a factory method to create an instance of the ApplicationUpdaterManager class.

You create an instance of the ApplicationUpdaterManager class by using one of the overloads of the GetUpdater method that are shown in the following code sample.

 [C#]
public static ApplicationUpdaterManager GetUpdater( )
public static ApplicationUpdaterManager GetUpdater( string applicationId )

[Visual Basic]
Public Overloads Shared Function GetUpdater() As ApplicationUpdaterManager
Public Overloads Shared Function GetUpdater(ByVal applicationId As String) As ApplicationUpdaterManager
  

Both overloads ultimately run the code in the second overload:

  • The first overload takes no arguments and internally retrieves the application identifier from the client configuration file. It then calls the second overload.
  • The second overload takes one argument of the application identifier as a string. The code verifies whether an updater currently exists for this applicationId, and if an updater does exist, the code returns that instance. If an updater does not exist, the code creates a new instance, adds it to the hash table of updaters, and returns it to the calling code. You can use this overload when you want to use an applicationId from a source other than the default location in the application configuration file.

The following code sample shows how to use the GetUpdater method to retrieve an instance of the ApplicationUpdaterManager.

 [C#]
ApplicationUpdaterManager updater = ApplicationUpdaterManager.GetUpdater();

[Visual Basic]
Dim WithEvents updater As ApplicationUpdaterManager 
updater = ApplicationUpdaterManager.GetUpdater()
  

Check for Updates

The ApplicationUpdaterManager class contains the CheckForUpdates methods that you can use to query the server for available updates for the client application.

The CheckForUpdates method has two overloads as shown in the following code sample.

 [C#]
public Manifest[] CheckForUpdates()
public Manifest[] CheckForUpdates( Uri location )

[Visual Basic]
Public Overloads Function CheckForUpdates() As Manifest()
Public Overloads Function CheckForUpdates(ByVal location As Uri) As Manifest()
  

Each of these overloads ultimately runs the code in the third overload:

  • The first overload takes no arguments and internally retrieves the location of the server manifest from the manifestUri attribute of the client configuration file. It then calls the second overload.
  • The second overload takes one argument of the location as a URI. It starts by querying whether there are any pending updates in the task registry. If there are, it raises the PendingUpdatesDetected event. For more information about this event, see Handle Pending Updates. The CheckForUpdates method then uses the ManifestManager.GetManifests method to retrieve any unapplied manifests from the server and returns them to the client application. It returns an array of manifests so that the primary manifest and any number of included manifests can be returned.

The following code sample shows how to use the CheckForUpdates method to retrieve the array manifests from the server.

[C#]
Manifest[] manifests = updater.CheckForUpdates();

[Visual Basic]
Dim manifests As Manifest() = updater.CheckForUpdates()
  

Each Manifest object in the returned array represents a manifest file from the server. It contains properties that represent the elements and attributes from the manifest XML.

Handle Pending Updates

When a task is started by the Updater Application Block, its details are entered into the task registry for tracking purposes. When the task finishes, that entry is deleted from the registry.

If an application session ends leaving tasks unfinished, the registry retains a record of those tasks, and when a new session calls the CheckForUpdates method, the PendingUpdatesDetected event is raised. You can handle this event in the client application and either resume or cancel the tasks. If the pending task is resumed and fails again, it remains in the task registry and the manifest is not committed. The task will be retried on each update until the client application calls the CancelPendingUpdate method. If the client application does not call the ResumePendingUpdate method from the OnPendingUpdatesDetected event, the pending task is canceled to enable a new task to be started.

The PendingUpdatesDetected event contains a PendingUpdatesDetectedEventArgs parameter. This parameter is an array of pending Manifests corresponding to UpdaterTasks. You can use the information in this parameter to decide what action to take. The ApplicationUpdaterManager provides two relevant methods to handle the PendingUpdatesDetected event; ResumePendingUpdates resumes the updates according to their state, and CancelPendingUpdates removes the updates from the task registry.

The following code sample shows how to use the ResumePendingUpdates and CancelPendingUpdates methods.

 [C#]
updater.ResumePendingUpdates();
updater.CancelPendingUpdates();

[Visual Basic]
updater.ResumePendingUpdates()
updater.CancelPendingUpdates()
  

Download Updates

After the array of manifests is retrieved by the client application, business logic or user decisions can be made about which updates to download and activate. The Manifest object has an Apply property that must be set to true if the manifest is to be applied during the update process. You should ensure that you set the Apply property to true if a manifest is marked as mandatory. The following code sample shows how mark to all downloaded manifests to run.

 [C#]
foreach(Manifest m in manifests)
{
     m.Apply = true;
}

[Visual Basic]
Dim m As Manifest
For Each m In manifests
m.Apply = True
Next m
  

The ApplicationUpdaterManager class provides methods to download updates synchronously and asynchronously. You can use the Download method to download the updates synchronously. You can use the BeginDownload method to download the updates asynchronously. This class also provides a CancelDownload method you can use to cancel an asynchronous download.

Synchronous Downloads

The Download method takes two parameters, an array of manifests to process and a TimeSpan to wait for the download process. You must make sure that you set this TimeSpan appropriately to ensure that the download process can complete and does not time out. The following code sample shows a call to the Download method.

 [C#]
updater.Download( manifests, TimeSpan.FromMinutes(2) );

[Visual Basic]
Updater.Download( manifests, TimeSpan.FromMinutes(2) )
  

The code in the Download method loops through the manifests, and for each one that is marked for processing; the code creates a new UpdaterTask and saves the task in the task registry. This is to ensure that if the process is interrupted, it can be later resumed.

If the UpdaterTask includes any files to download, the Download method calls the internal downloadManager.SubmitTask method to initiate the download process. This method determines the downloader type from the manifest and then retrieves any required configuration information from the downloaders element in the client application configuration file and instantiates the downloader. If no downloader is specified, the default BITSDownloader is used. The method then calls the Download method of the specified downloader type. This method transfers the files from the server location to the temporary folder on the client computer.

Asynchronous Downloads

The BeginDownload method takes only one parameter, an array of manifests to process. The following code sample shows a call to the BeginDownload method.

 [C#]
updater.BeginDownload( manifests );

[Visual Basic]
Updater.BeginDownload( manifests )
  

The code in the BeginDownload method loops through the manifests and for each one that is marked for processing, the code creates a new UpdaterTask and saves the task in the updater registry. This is to ensure that if the process is interrupted, it can be later resumed.

f the UpdaterTask includes any files to download, the BeginDownload method calls the internal downloadManager.SubmitTaskAsync method to initiate the download process. This method determines the downloader type from the manifest and then retrieves any required configuration information from the downloaders element in the client application configuration file and instantiates the downloader. If no downloader is specified, the default BITSDownloader is used.

The method then calls the BeginDownload method of the specified downloader type. This method transfers the files from the server location to the temporary folder on the client computer.

The ApplicationUpdaterManager also includes a CancelDownload method you can use to cancel an asynchronous update. This stops the download process and removes the task from the task registry.

Activate Updates

After the download process has been executed, you can perform any post-download activation tasks that your application requires. For example, your application may require that files be copied to a final destination or it may require execution of a Windows Installer package. The Updater Application Block includes the activation processors listed in Table 3.5.

Table 3.5: Activation processors

NameDescription
ApplicationDeployProcessorCopies non-transient files to a location specified in the manifest.
FileCopyProcessorCopies files to a destination folder.
FileDeleteProcessorDeletes files in a specified folder.
FolderCopyProcessorCopies a folder and its contents to a specified folder.
FolderDeleteProcessorDeletes a specified folder.
MSIProcessorRuns a Windows Installer package.
WaitForApplicationExitProcessorBatches the file copy process until the client application exits and then executes the processors.
GACUtilProcessorUses Gacutil.exe to install specified downloaded assemblies into the global assembly cache.
InstallUtilProcessorUses Installutil.exe to install or uninstall server resources.
ValidateHashProcessorCompares the hash value of a downloaded file with the hash value supplied in the manifest to ensure that the correct file has been downloaded.
UncompressProcessorUses Expand.exe to expand compressed files.

For more information about the activation processors, see IActivationProcessor Implementations.

You can develop custom activation processors by implementing the IActivationProcessor, which is defined in the Updater Application Block. For more information about developing custom processors, see Adding an Activation Processor.

Define the Required Activation Processors

You specify which activation processors to use in the activation element of the manifest file.

The tasks element can contain many task elements. This means that you can perform more than one post-download process for each manifest. For example, you may want to copy the downloaded files to a specific location before running a script.

Some of the activation processors require additional information to be specified. You can use custom attributes of the task element to specify this information. The following example shows how to pass additional information to the MSIProcessor.

<tasks>
  <task type= "Microsoft.ApplicationBlocks.Updater.ActivationProcessors.MSIProcessor, Microsoft.ApplicationBlocks.Updater.ActivationProcessors" 
name="MSIProcessor">
    <config>
      <installType>Install</installType>
      <packagePath>SimpleAppSetup.msi</packagePath>
      <propertyValues>ACTION=INSTALL</propertyValues>
      <uiLevel>msiUILevelProgressOnly</uiLevel>
    </config>
  </task>
</tasks>
  

Perform the Activation

After the file download is complete, you can use the Activate method of the ApplicationUpdaterManager to initiate the activation process. This method should be called only when the download of all the manifests has been successfully completed. This method takes one parameter that contains an array of manifests to activate. The following code sample shows a call to the Activate method.

 [C#]
updater.Activate( manifests );

[Visual Basic]
Updater.Activate( manifests )
  

For each manifest that should be applied, this method calls the ActivationManager.SubmitTask method, which in turn calls the ActivationManager.Activate method. This method determines the activation processor types from the activation element in the manifest, initializes the processors, prepares it for execution, and then runs the activation process.

If an activation fails, the code calls the OnError method of each executed activation processor in order to allow it to perform any remedial processing.

Handle Progress Events

The Updater Application Block exposes many events that you can use to track the progress of an application update. The key events are the pending updates event, the download events, and the activation events. You can handle these events in your client application to track the progress of the download and activation processes and respond to any errors that may occur.

Pending Updates Event

The ApplicationUpdaterManager class exposes the PendingUpdatesDetected event. This event is raised from the CheckForPendingUpdates method when pending updates are detected. You can use the event to resume or cancel pending updates.

This event provides an object argument that identifies the sender of the event and a PendingUpdatesDetectedEventArgs argument that contains an array of manifests corresponding to the pending tasks. You can use the PendingUpdatesDetectedEventArgs argument to access the manifest information of the tasks.

The following code sample shows how you can handle this event in your client application.

 [C#]
// declare the event
updater.PendingUpdatesDetected += new PendingUpdatesDetectedEventHandler(updater_PendingUpdatesDetected);

// handle the event
private static void updater_ PendingUpdatesDetected( object sender, PendingUpdatesDetectedEventArgs e )
{
    Console.WriteLine("Pending updates detected);
    updater.ResumePendingUpdates();
}

[Visual Basic]
Private Sub updater_PendingUpdatesDetected(ByVal sender As Object, ByVal e As PendingUpdatesDetectedEventArgs) Handles updater.PendingUpdatesDetected
    Console.WriteLine("Pending updates detected")
    updater.ResumePendingUpdates()
End Sub
  

Download Events

The DownloadManager class internally exposes four download events. These are passed through the call stack and exposed to the client application from the ApplicationUpdaterManager class. The downloaded events that are exposed are the following:

  • ApplicationUpdaterManager.DownloadStarted. This event is raised immediately before the IDownloader implementation starts the download. You can use it to track the start of each manifest within an update.

    This event provides an object argument that identifies the sender of the event and a DownloadStartedEventArgs argument that contains the Manifest object corresponding to the task. You can use the DownloadStartedEventArgs argument to access the manifest information of the current download. The argument also has a Cancel attribute that you can use to cancel the download.

  • ApplicationUpdaterManager.DownloadProgress. This event is raised whenever the downloader job is modified. You can use it to track the overall progress of a job in percentage terms.

    This event provides the object argument that identifies the sender of the event and a DownloadProgressEventArgs argument that includes the following information about the download:

    • bytesTotal
    • bytesTransferred
    • filesTotal
    • filesTransferred
    • manifest

    You can use the DownloadTaskProgressEventArgs to track the overall progress of the download or to extract manifest information of the current download. The argument also has a Cancel attribute that you can use to cancel the download.

  • ApplicationUpdaterManager.DownloadError. This event is raised whenever the downloader job raises an exception. You can use it to handle the exception in your client application.

    This event provides an object argument that identifies the sender of the event and a ManifestErrorEventArgs argument that contains both the Exception object that was raised and a Manifest object corresponding to the task. You can use the ManifestErrorEventArgs to extract manifest information of the current download.

  • ApplicationUpdaterManager.DownloadCompleted. This event is raised whenever the downloader job finishes. You can use it to notify the client application the download finished.

    This event provides an object argument that identifies the sender of the event and a ManifestEventArgs argument that contains the Manifest object corresponding to the task. You can use the ManifestEventArgs to extract manifest information of the current download.

The following code sample shows how you can handle these download events in your client application.

 [C#]
// declare the events
updater.DownloadStarted += new DownloadStartedEventHandler(updater_DownloadStarted);
updater.DownloadProgress += new DownloadProgressEventHandler(updater_DownloadProgress);
updater.DownloadError += new DownloadErrorEventHandler(updater_DownloadError);
updater.DownloadCompleted += new DownloadCompletedEventHandler(updater_DownloadCompleted);

// handle the events
private static void updater_DownloadStarted( object sender, DownloadStartedEventArgs e )
{
Console.WriteLine( "DownloadStarted for manifest: {0}", e.Manifest.ManifestId );
}

private static void updater_DownloadProgress( object sender, DownloadProgressEventArgs e)
{
Console.WriteLine( "DownloadProgress for manifest: {0} - Files: {1}/{2} - Bytes: {3}/{4}", e.Manifest.ManifestId, e.FilesTransferred, e.FilesTotal, e.BytesTransferred, e.BytesTotal );
}

private static void updater_DownloadError( object sender, ManifestErrorEventArgs e)
{
Console.WriteLine( "DownloadError for manifest: {0}", e.Manifest.ManifestId );
}

private static void updater_DownloadCompleted( object sender, ManifestEventArgs e)
{
Console.WriteLine( "DownloadCompleted for manifest: {0}", e.Manifest.ManifestId );
}

[Visual Basic]
Private Sub updater_DownloadStarted(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.DownloadStartedEventArgs) Handles updater.DownloadStarted
    Console.WriteLine("DownloadStarted for manifest: {0}", e.Manifest.ManifestId)
End Sub

Private Sub updater_DownloadProgress(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.DownloadProgressEventArgs) Handles updater.DownloadProgress
    Console.WriteLine("DownloadProgress for manifest: {0} - Files: {1}/{2} - Bytes: {3}/{4}", e.Manifest.ManifestId, e.FilesTransferred, e.FilesTotal, e.BytesTransferred, e.BytesTotal)
End Sub

Private Sub updater_DownloadError(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ManifestErrorEventArgs) Handles updater.DownloadError
    Console.WriteLine("DownloadError for manifest: {0}", e.Manifest.ManifestId)
End Sub

Private Sub updater_DownloadCompleted(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ManifestEventArgs) Handles updater.DownloadCompleted
    Console.WriteLine("DownloadCompleted for manifest: {0}", e.Manifest.ManifestId)
End Sub
  

Activation Events

The ActivationManager class internally exposes five activation events. These are passed through the call stack and exposed to the client application from the ApplicationUpdaterManager class. The activation events that are exposed are the following:

  • ApplicationUpdaterManager.ActivationInitializing. This event is raised immediately before the instantiation of the IActivationProcessor implementations specified in the manifest file. You can use it to track the start of the initialization process.

    This event provides an object argument that identifies the sender of the event and a ManifestEventArgs argument that contains the Manifest object corresponding to the task. You can use the ManifestEventArgs to extract manifest information of the current download.

  • ApplicationUpdaterManager.ActivationInitializationAborted. This event is raised from the ActivationPausedException if the processors are to be deliberately aborted, for example, when using the WaitForApplicationProcessor.

    This event provides an object argument that identifies the sender of the event and a ManifestEventArgs argument that contains the Manifest object corresponding to the task. You can use the ManifestEventArgs to extract manifest information of the current download.

  • ApplicationUpdaterManager.ActivationStarted. This event is raised at the start of the execution phase, before the Execute method is called. You can use it to track the start of the execution process.

    This event provides an object argument that identifies the sender of the event and a ManifestEventArgs argument that contains the Manifest object corresponding to the task. You can use the ManifestEventArgs to extract manifest information of the current download.

  • ApplicationUpdaterManager.ActivationError. This event is raised if an exception, other than the ActivationPausedException, is raised during the call to the Init, PrepareExecute, or Execute method. You can use it to handle errors as they occur.

    After this event is raised, the ActivationManager calls the executed activation processors to notify them of the error and allow them to perform corrective tasks.

    This event provides an object argument that identifies the sender of the event and a ManifestErrorEventArgs argument that contains both the Exception object that was raised and a Manifest object corresponding to the task. You can use the ManifestErrorEventArgs to extract manifest information of the current download.

  • ApplicationUpdaterManager.ActivationCompleted. This event is raised at the end of the execution process, regardless of whether it succeeded or failed. You can use it to notify the client application of the end of the activation process.

    This event provides an object argument that identifies the sender of the event and an ActivationCompleteEventArgs argument that contains both a success flag and a Manifest object corresponding to the task. You can use the ActivationCompleteEventArgs to extract manifest information of the current download.

The following code sample shows how you can handle these activation events in your client application.

 [C#]
updater.ActivationInitializing += new ActivationInitializingEventHandler(updater_ActivationInitializing);
updater.ActivationInitializationAborted += new ActivationInitializationAbortedEventHandler( updater_ActivationInitializationAborted);
updater.ActivationStarted += new ActivationStartedEventHandler(updater_ActivationStarted);
updater.ActivationError += new ActivationErrorEventHandler(updater_ActivationError);
updater.ActivationCompleted +=new ActivationCompletedEventHandler(updater_ActivationCompleted);

private void updater_ActivationInitializing(object sender, ManifestEventArgs e)
{
Console.WriteLine( "ActivationInitializing for manifest: {0}",  e.Manifest.ManifestId);
}

private void updater_ActivationInitializationAborted(object sender, ManifestEventArgs e)
{
Console.WriteLine( "ActivationInitializationAborted for manifest: {0}",  e.Manifest.ManifestId);
}

private void updater_ActivationStarted(object sender, ManifestEventArgs e)
{
Console.WriteLine( "ActivationStarted for manifest: {0}", e.Manifest.ManifestId);
}

private void updater_ActivationError(object sender, ManifestErrorEventArgs e)
{
Console.WriteLine( "ActivationError for manifest: {0} {1}", e.Manifest.ManifestId, e.Exception.Message);
}

private void updater_ActivationCompleted(object sender, ActivationCompleteEventArgs e)
{
Console.WriteLine( "ActivationCompleted for manifest: {0}",  e.Manifest.ManifestId);
}

[Visual Basic]
Private Sub updater_ActivationInitializing(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ManifestEventArgs) Handles updater.ActivationInitializing
  Console.WriteLine("ActivationInitializing for manifest: {0}", e.Manifest.ManifestId)
End Sub

Private Sub updater_ActivationInitializationAborted(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ManifestEventArgs) Handles updater.ActivationInitializationAborted
    Console.WriteLine("ActivationInitializationAborted for manifest: {0}", e.Manifest.ManifestId)
End Sub

Private Sub updater_ActivationStarted(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ManifestEventArgs) Handles updater.ActivationStarted
    Console.WriteLine("ActivationStarted for manifest: {0}", e.Manifest.ManifestId)
End Sub

Private Sub updater_ActivationError(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ManifestErrorEventArgs) Handles updater.ActivationError
    Console.WriteLine("ActivationError for manifest: {0} {1}", e.Manifest.ManifestId, e.Exception.Message)
End Sub

Private Sub updater_ActivationCompleted(ByVal sender As Object, ByVal e As Microsoft.ApplicationBlocks.Updater.ActivationCompleteEventArgs) Handles updater.ActivationCompleted
    Console.WriteLine("ActivationCompleted for manifest: {0}", e.Manifest.ManifestId)
End Sub
  

Start | Previous | Next

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Did you find this helpful?
(1500 characters remaining)
© 2013 Microsoft. All rights reserved.