IIS 5.0IIS 5.1IIS 6.0IISVisual Studio .NET 2003Windows 2003.NET 1.1Windows 2000Windows XPIntermediateDevVisual StudioWindows.NETC#
使用 Updater Block






4.56/5 (32投票s)
2005年4月13日
7分钟阅读

260976

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)(用于开箱即用的下载器正常工作)。
步骤
- 创建一个简单的 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 添加到应用程序:添加 -> 新建项 -> 应用程序配置文件。
- 构建应用程序。
- 将 updater 应用程序块添加到应用程序。
- 必须引用的三个程序集位于 C:\Program Files\Microsoft Patterns & Practices\Updater Application Block 2.0\src\cs 文件夹下(如果安装 updater block 时选择了默认设置)。
- 这三个 DLL 文件可以在上述通用文件夹中 ActivationProcessors、Downloaders 和 Updater 项目的 bin/debug 文件夹中找到。
- 为创建的示例应用程序添加对这三个 DLL 的引用。
- Microsoft.ApplicationBlocks.Updater.ActivationProcessors.dll
- Microsoft.ApplicationBlocks.Updater.Downloaders.dll
- Microsoft.ApplicationBlocks.Updater.dll
- 将文档末尾的代码添加到应用程序中,该代码是处理下载的主体(从 #region Auto-Update Stuff To #endregion)。
注意:可下载的源文件包含此内容,但没关系。
- 将以下代码添加到
SampleForm
类的构造函数中,以启动 updater manager。InitializeAutoUpdater ();
- 使用 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。
- 更新应用程序块的属性。
ApplicationID
:SampleApplication。BasePath
:C:\Temp\UpdaterTest\UAB。ManifestUri
:https:///ApplicationBlockServer/ServerManifest.xml。注意:
ManifestUri
将指向稍后需要创建的 URL。
- 右键单击“Updater Application Block”,然后选择“新建”->“Downloaders”。
- 右键单击“Downloaders”,然后选择“新建”->“BITSDownloader”。
- 保存。
- 部署客户端。
- 生成 SampleApplication 项目。
- 将项目输出从 bin/Debug 文件夹复制到 C:\Temp\UpdaterTest 文件夹。需要复制的文件是:
- 所有 DLL,包括以下内容:
- Microsoft.ApplicationBlocks.Updater.ActivationProcessors.dll
- Microsoft.ApplicationBlocks.Updater.dll
- Microsoft.ApplicationBlocks.Updater.Downloaders.dll
- 应用程序 exe:SampleApplication.exe
- 配置文件:SampleApplication.exe.config
- 所有 DLL,包括以下内容:
- 将项目根文件夹中的 updaterconfiguration.config 和 securitycryptographyconfiguration.config 文件复制到 UpdaterTest 文件夹。
- 将项目更改为创建服务器应用程序。
服务器应用程序将是部署在 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")]。
- 构建应用程序。
- 部署服务器应用程序。
应用程序的新版本将部署在服务器上,可以从那里下载。
- 在 C:\inetpub\wwwroot 下创建一个名为 ApplicationBlockServer 的文件夹。
- 打开 IIS 管理器(开始 -> 运行 -> Inetmgr)。
- 在 IIS 管理器中,导航到“默认网站”。
- 右键单击“默认网站”,然后选择“新建”->“虚拟目录”。
- 创建一个别名为 ApplicationBlockServer 的虚拟目录,并将该目录指向上面创建的 ApplicationBlockServer 文件夹。
- 在 c:\inetpub\wwwroot\ ApplicationBlockServer 文件夹下创建一个名为 1.0.0.1 的新文件夹。
- 将上一步中生成的 SampleApplication.exe 文件复制到新创建的 1.0.0.1 文件夹。
- 生成服务器的 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”。
- 在“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