65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Updater Block

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (32投票s)

2005年4月13日

7分钟阅读

viewsIcon

260976

downloadIcon

1414

一个标准的实现,展示了如何将 Updater Block 2.0 包含在 Windows 窗体应用程序中。

引言

我一直在尝试将 updater block 包含到我的应用程序中。应用程序块附带的快速入门指南中有一些非常好的示例,但要弄清楚哪些文件需要放在哪里、需要进行哪些设置以及如何进行设置才能让自己的示例正常工作,这花费了我相当长的时间。因此,我想我应该发布我生成的示例实现,并附带一个分步指南,以便其他人以后尝试使用它时不必费力。

注意:有关 updater block 版本 1.0 的优秀教程可以在这里找到。

下面的示例尝试展示 Updater Block 2.0 版本的用法。

必备组件

  • 必须下载并安装 Enterprise Library 和 Updater Application Block。Enterprise Library 可以从这里下载。
  • Updater Block 可以从这里下载。

系统要求

  • 支持的操作系统:Windows XP。
  • Windows XP Professional。
  • Internet Information Server 版本 5.0 或更高版本。
  • Microsoft .NET FrameWork 版本 1.1 SDK。
  • Microsoft Visual Studio 2003。
  • Background Intelligent Transfer Service (BITS)(用于开箱即用的下载器正常工作)。

步骤

  1. 创建一个简单的 Windows 窗体应用程序。
    • 打开 VS .NET 编辑器,选择 文件 -> 新建项目 -> Windows 应用程序。
    • 将名称更改为 SampleApplication。
    • 将默认生成的窗体命名为 SampleForm.cs
    • SampleForm 上添加一个标签,并将其文本设置为“版本 1.0.0.0”。
    • 在窗体上添加一个按钮,并将其文本更改为“退出”。添加退出应用程序的事件处理程序 - Application.Exit();
    • 添加一个名为 eventList 的列表框。
    • 打开 AssemblyInfo.cs 并将应用程序的版本更改为 1.0.0.0:[assembly: AssemblyVersion("1.0.0.0")]
    • Main () 主体中的行更改为 Application.Run(new SampleForm());
    • app.config 添加到应用程序:添加 -> 新建项 -> 应用程序配置文件。
    • 构建应用程序。
  2. 将 updater 应用程序块添加到应用程序。
    • 必须引用的三个程序集位于 C:\Program Files\Microsoft Patterns & Practices\Updater Application Block 2.0\src\cs 文件夹下(如果安装 updater block 时选择了默认设置)。
    • 这三个 DLL 文件可以在上述通用文件夹中 ActivationProcessors、Downloaders 和 Updater 项目的 bin/debug 文件夹中找到。
    • 为创建的示例应用程序添加对这三个 DLL 的引用。
      1. Microsoft.ApplicationBlocks.Updater.ActivationProcessors.dll
      2. Microsoft.ApplicationBlocks.Updater.Downloaders.dll
      3. Microsoft.ApplicationBlocks.Updater.dll
    • 将文档末尾的代码添加到应用程序中,该代码是处理下载的主体(从 #region Auto-Update Stuff To #endregion)。

      注意:可下载的源文件包含此内容,但没关系。

    • 将以下代码添加到 SampleForm 类的构造函数中,以启动 updater manager。
      InitializeAutoUpdater ();
  3. 使用 Enterprise Library Configuration Tool 更新 App.Config 文件。
    • 从 开始 -> 所有程序 -> Microsoft Patterns and Practices -> Updater Application Block V2 -> Enterprise Library Configuration Tool 打开该工具。
    • 在 Configuration tool 控制台中,选择 文件 -> 打开应用程序,浏览到 App.Config 文件,选择并单击“打开”。
    • 在根“Enterprise Library Configuration”下出现了一个新项“Application”。
    • 右键单击“Application”,然后选择“新建”->“Updater Application Block Configuration”。
    • 添加了 Configuration、Cryptography 和 Updater Application Blocks。
    • 更新应用程序块的属性。
      1. ApplicationID:SampleApplication。
      2. BasePathC:\Temp\UpdaterTest\UAB。
      3. ManifestUrihttps:///ApplicationBlockServer/ServerManifest.xml

        注意:ManifestUri 将指向稍后需要创建的 URL。

    • 右键单击“Updater Application Block”,然后选择“新建”->“Downloaders”。
    • 右键单击“Downloaders”,然后选择“新建”->“BITSDownloader”。
    • 保存。
  4. 部署客户端。
    • 生成 SampleApplication 项目。
    • 将项目输出从 bin/Debug 文件夹复制到 C:\Temp\UpdaterTest 文件夹。需要复制的文件是:
      1. 所有 DLL,包括以下内容:
        1. Microsoft.ApplicationBlocks.Updater.ActivationProcessors.dll
        2. Microsoft.ApplicationBlocks.Updater.dll
        3. Microsoft.ApplicationBlocks.Updater.Downloaders.dll
      2. 应用程序 exe:SampleApplication.exe
      3. 配置文件:SampleApplication.exe.config
    • 将项目根文件夹中的 updaterconfiguration.configsecuritycryptographyconfiguration.config 文件复制到 UpdaterTest 文件夹。
  5. 将项目更改为创建服务器应用程序。

    服务器应用程序将是部署在 c:\temp\ UpdaterTest 的应用程序的更新版本。

    • 在 VS.NET 编辑器中打开 SampleApplication 解决方案。
    • 在设计器模式下打开 SampleForm,并在窗体上进行明显更改。将标签文本更改为“版本 1.0.0.1”,将窗体文本更改为“Sample Form New Version”。
    • 打开 AssemblyInfo.cs 并将程序集版本更改为 1.0.0.1:[assembly: AssemblyVersion("1.0.0.1")]。
    • 构建应用程序。
  6. 部署服务器应用程序。

    应用程序的新版本将部署在服务器上,可以从那里下载。

    • C:\inetpub\wwwroot 下创建一个名为 ApplicationBlockServer 的文件夹。
    • 打开 IIS 管理器(开始 -> 运行 -> Inetmgr)。
    • 在 IIS 管理器中,导航到“默认网站”。
    • 右键单击“默认网站”,然后选择“新建”->“虚拟目录”。
    • 创建一个别名为 ApplicationBlockServer 的虚拟目录,并将该目录指向上面创建的 ApplicationBlockServer 文件夹。
    • c:\inetpub\wwwroot\ ApplicationBlockServer 文件夹下创建一个名为 1.0.0.1 的新文件夹。
    • 将上一步中生成的 SampleApplication.exe 文件复制到新创建的 1.0.0.1 文件夹。
  7. 生成服务器的 Manifest 文件。
    • 打开与 updater block 一起安装的 Manifest Editor 工具(开始 -> 所有程序 -> Microsoft Patterns and Practices -> Updater Application Block V2 -> Manifest Editor Tool。
    • 在“Manifest Properties”选项卡下,单击“Generate”按钮并生成 manifest ID。选中“Mandatory”复选框。
    • 输入描述“Sample Application Version 1.0.0.1”。
    • 在“application properties”选项卡中,将应用程序 ID 输入为“SampleApplication”,将位置输入为“.”。
    • 入口点是“SampleApplication.exe”。
    • File URI 为 https:///ApplicationBlockServer/1.0.0.1
    • 源文件夹是“C:\Inetpub\wwwroot\ApplicationBlockServer\1.0.0.1”。
    • 单击“Add”按钮,然后从 1.0.0.1 文件夹中选择 SampleApplication.exe。该文件应出现在“Files”列表中。
    • 在“activation process”选项卡中,输入进程名称为 AppDeploy,处理器类型为“Application Deploy”,然后按“Add”。
    • 输入进程名称为“WFE”,处理器类型为“Wait For Exit”,然后按 Add。将弹出一个新窗口提示添加进程名称。按 Cancel。
    • 单击 Validate 按钮以验证生成的 manifest。
    • 单击 Save 按钮将 manifest 保存在“C:\Inetpub\wwwroot\ApplicationBlockServer”下,文件名为“ServerManifest.xml”。
  8. 在“C:\Temp\UpdaterTest”下运行应用程序。

    应用程序在一段时间后会弹出一个对话框,提示有新版本可用,是否要下载。单击“是”。将下载新版本,该版本将显示在列表框 eventList 中。下载完成后,会提示您重新启动应用程序。关闭应用程序,然后再次启动。将打开版本 1.0.0.1。

    附录

    • 应用程序更新完成后,将在 UpdaterTest 文件夹中创建一个名为 UAB 的文件夹。此文件夹提供了有关最新版本的信息。
    • 据我所理解,manifest ID 在服务器上维护,如果客户端更新发生,manifest ID 会放入 UAB 文件夹。如果服务器的 manifest ID 与客户端的不同(或者客户端没有 UAB 文件夹,表示尚未进行任何更新),则 updater block 会启动。
    • 要在服务器上部署应用程序的新版本,请创建一个名为 1.0.0.2 的新文件夹,并将所有文件放在该位置(命名约定只是为了方便,并非强制规则),然后生成一个新的服务器 manifest 文件,其中包含新的 Manifest ID,并替换旧的 manifest 文件。
    • 我还没有检查自动更新功能,即客户端可以安排在固定时间间隔 ping 服务器。但这应该很简单,只需设置某个属性即可。
    • 下面的代码有一个线程,每 10 秒 ping 一次服务器。这部分可以删除。

嘿,这只是一个标准的实现。

Auto Update Code to be pasted in the application

#region Auto-Update Stuff
 
    private Thread pollThread = null;
    private int manifestDownloaded = 0;
            
    private void CheckAndUpdate()
    {
       try
       {
          // Get the updater manager
          ApplicationUpdaterManager updater = 
              ApplicationUpdaterManager.GetUpdater();
                        
          // Subscribe for various events
          updater.DownloadStarted +=
              new DownloadStartedEventHandler(updater_DownloadStarted);
          updater.DownloadProgress += 
              new DownloadProgressEventHandler(updater_DownloadProgress);
          updater.DownloadCompleted += 
              new DownloadCompletedEventHandler(updater_DownloadCompleted);
          updater.DownloadError += 
              new DownloadErrorEventHandler(updater_DownloadError);
          updater.ActivationInitializing += 
              new ActivationInitializingEventHandler(updater_ActivationInitializing);
          updater.ActivationStarted += 
              new ActivationStartedEventHandler(updater_ActivationStarted);
          updater.ActivationInitializationAborted += 
              new ActivationInitializationAbortedEventHandler(
              updater_ActivationInitializationAborted);
          updater.ActivationError += 
              new ActivationErrorEventHandler(updater_ActivationError);
          updater.ActivationCompleted +=
              new ActivationCompletedEventHandler(updater_ActivationCompleted);
 
          // Loop till the updates are available
 
           Manifest[] manifests = null;
           while(true)
           {
              manifests = updater.CheckForUpdates();
              if(manifests.Length > 0)
              {
                 // Prompt user if he wants to apply the updates
                 if( MessageBox.Show(this,
                    "Update for Auto Inproc Application is available,"+
                    " do you want to apply the update?",
                    "Update",MessageBoxButtons.YesNo)== DialogResult.Yes)
                 {
                    foreach(Manifest m in manifests)
                    {
                       m.Apply = true;
                    }
                    // update the application as per manifest details.
                    updater.Download( manifests, TimeSpan.MaxValue );
                    if(manifestDownloaded == manifests.Length)
                    {
                       updater.Activate( manifests );
                       manifestDownloaded = 0;
                    }
                    break;
                 }
                 else
                 {
                    Thread.Sleep(10000);
                 }
              }
              else
              {
                 Thread.Sleep(10000);
              }
           }
        }
        catch(ThreadAbortException)
        {
           // Do nothing if the thread is being aborted, 
           //as we are explicitly doing it
        }
        catch(Exception ex)
        {
           MessageBox.Show(this,ex.Message,"Error",
                MessageBoxButtons.OK,MessageBoxIcon.Error);
        }
     }
 
     private void exitButton_Click(object sender, System.EventArgs e)
     {
        Application.Exit();
     }
 
     private void updater_DownloadStarted(object sender, 
         DownloadStartedEventArgs e)
     {
        UpdateList("DownloadStarted for manifest: " + e.Manifest.ManifestId);
     }
 
     private void updater_DownloadProgress(object sender, 
                                       DownloadProgressEventArgs e)
     {
        UpdateList("DownloadProgress for manifest: "+ e.Manifest.ManifestId +
          "- Files: "+e.FilesTransferred+"/"+e.FilesTotal+
          " - Bytes: "+e.BytesTransferred+"/"+e.BytesTotal);
     }
 
     private void updater_DownloadCompleted(object sender, 
                                   ManifestEventArgs e)
     {
        UpdateList("DownloadCompleted for manifest: " + 
                                 e.Manifest.ManifestId);
        manifestDownloaded++;
     }
 
     private void updater_DownloadError(object sender, 
                           ManifestErrorEventArgs e)
     {
        UpdateList("DownloadError for manifest: " + 
                       e.Manifest.ManifestId +"\n"+e.Exception.Message);
     }
 
     private void updater_ActivationInitializing(object sender, 
                              ManifestEventArgs e)
     {
        UpdateList("ActivationInitializing for manifest: " + 
                                      e.Manifest.ManifestId);
     }
 
     private void updater_ActivationStarted(object sender, ManifestEventArgs e)
     {
        UpdateList("ActivationStarted for manifest: " + e.Manifest.ManifestId);
     }
 
     private void updater_ActivationInitializationAborted(object sender,
                                            ManifestEventArgs e)
     {
        UpdateList("ActivationInitializationAborted for manifest: " + 
                                      e.Manifest.ManifestId);
        MessageBox.Show(this,
           "The Application needs to restart for applying the updates," +
           " please restart the application.",
           "Auto Inproc Updates",MessageBoxButtons.OK,
           MessageBoxIcon.Information);
     }
 
     private void updater_ActivationError(object sender, 
                                       ManifestErrorEventArgs e)
     {
        UpdateList("ActivationError for manifest: " + e.Manifest.ManifestId +
            "\n"+e.Exception.Message);
     }
 
     private void updater_ActivationCompleted(object sender, 
                             ActivationCompleteEventArgs e)
     {
        UpdateList("ActivationCompleted for manifest: " + e.Manifest.ManifestId);
     }
 
     private void UpdateList(string displayString)
     {
        eventList.Items.Add(displayString);
        eventList.Update();
     }
 
    private void InitializeAutoUpdater ()
    {
       // Seperate thread is spun to keep polling for updates
       ThreadStart checkUpdateThreadStart = new ThreadStart(CheckAndUpdate);
       pollThread = new Thread(checkUpdateThreadStart);
       pollThread.Start();     
    }
#endregion
© . All rights reserved.