zoukankan      html  css  js  c++  java
  • 使用Updater Application Block实现自动更新例子

     

    Ø       使用Updater Application Block实现自动更新特性

    由于有了Smart Client技术,我们可以很好的将胖客户端和瘦客户端应用的优点结合在一起,适应医院使用实际情况的需要。Smart Client可以自动灵活地进行升级和更新从而简化了系统的维护;Smart Client可以充分的利用本地的计算资源,可以将HIS处理的载荷合理的分配给系统中的每一台计算机,提高了系统的响应和性能。

    微软公司提供的Microsoft Application Block为开发具有智能更新功能的.NET应用提供了极大的便利。在HIS Demo中我们重用并扩展了Updater Application Block UAB)等应用程序模块,实现了符合HIS应用实际需求的自动更新等功能。

    使用UAB可以实现对.NET应用智能更新支持,UAB为应用提供了下载,验证和后置处理机制。通过UAB提供的接口,我们可以轻易对UAB根据自己需要进行扩展。在HIS Demo中,我们使用BITS下载机制,保证系统的运作效率。UAB的工作流程如下图所示:

    UAB主要有四个模块组成Updater, Downloader, Validate以及Post Processor组成。Updater负责整个更新工作的管理;Downloader实现文件的下载,UAB中采用BITS (Background Intelligence Transfer Service)作为DownloaderUAB提供了IDownloader 接口,实现这个接口,开发者可以开发基于任意协议的下载器;Validator完成对下载文件的校验,UAB中提供KeyValidatorRSAValidator两个类,分别来实现对对称和非对称加密文件的校验;Post Processor则提供完成文件更新后需要进行的各种操作。

    Q        如何在应用中实现基本的自动更新功能?

    HIS Demo中将自动更新的主要功能封装在SelfUpdater类中(源文件HISDEMO \HISCLINIC \SelfUpdater.cs

    SelfUpdater类中通过InitUpdater()方法对Updater进行初始化,主要工作包括实例化ApplicationUpdateManager,为更新过程中主要的事件UpdaterAvailableFilesValidated等事件指定事件处理器

     

    /***********************************************************

    private void InitUpdater()

    {

    updater=new ApplicationUpdateManager();

    updater.UpdateAvailable += new UpdaterActionEventHandler(updater_UpdateAvailable);

        updater.FilesValidated += new UpdaterActionEventHandler(updater_FilesValidated);

    }

    /***********************************************************

    UpdaterAvailable事件当UAB发现服务器上有新的应用版本时发生,这时通常会询问用户是否要需要更新,如果用户选择需要则开始下载

    /***********************************************************

    /// <summary>

    ///当判定存在更新文件时相应的事件方法

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    private void updater_UpdateAvailable(object sender, UpdaterActionEventArgs e)

    {

    // Show a message allowing the user to determine if they would like to download the update

    // and perform the upgrade

    string message = String.Format(

                    "更新提示:现在服务器上的最新版本是 {0} , 需要更新吗?",

                    e.ServerInformation.AvailableVersion ) ;

        DialogResult dialog ;

        if(MsgBoxOwner!=null)

    dialog = MessageBox.Show(MsgBoxOwner, message, "更新提示",

    MessageBoxButtons.YesNo );

        else

            dialog = MessageBox.Show( message, "更新提示", MessageBoxButtons.YesNo );

                UpdaterArgs args=new UpdaterArgs();

     

    // The user has indicated they don't want to upgrade

        if( DialogResult.No == dialog )

            {

                //  stop the updater for this app

                updater.StopUpdater( e.ApplicationName );

                args.IsRunning=false;

            }

        Else

    {

                args.IsRunning=true;

            }

    //

        if(UpdaterStateCallBack!=null)

                UpdaterStateCallBack(this,args);

    }

    /***********************************************************

    FilesValidated事件当更新文件成功下载并通过校验后发生,这时时通常会询问用户是否要需要运新更新后的程序,如果用户选择需要是则需要停止当前应用并启动更新后的应用

    /***********************************************************

    /// <summary>

    /// 当更新文件下载完毕时相应的事件方法

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    private void updater_FilesValidated(object sender, UpdaterActionEventArgs e)

    {

    //  Ask user if they want to use the new version of the application

        DialogResult dialog = MessageBox.Show(

                    "需要打开新的应用程序吗?",

                    "打开新版本?", MessageBoxButtons.YesNo );

     

        if( DialogResult.Yes == dialog )

            {

            // Load this applications configuration file to read the

            // UAB information and obtain the basedir

            XmlDocument doc = new XmlDocument();

            doc.Load( AppDomain.CurrentDomain.SetupInformation.ConfigurationFile );

            string baseDir = doc.SelectSingleNode(

            "configuration/appUpdater/UpdaterConfiguration/application/client/baseDir"

                        ).InnerText;

            // Figure out the path to AppStart.exe which we will chain to

            string newDir = Path.Combine( baseDir, "AppStart.exe" );

            // Launch AppStart.exe which will launch the new version

            ProcessStartInfo process = new ProcessStartInfo( newDir );

            process.WorkingDirectory = Path.Combine( newDir ,

            e.ServerInformation.AvailableVersion );

            Process.Start( process );

            StopUpdate();

            Environment.Exit( 0 );

            }

    }

    /**********************************************************

    使用自动更新是在主表单中实例化SelfUpdater类即可。

    /***********************************************************

    public frmMainForm()

    {

        //

        // Windows 窗体设计器支持所必需的

        //

        InitializeComponent();

        //Init update obeject

    updater=new SelfUpdater();

    ……

    }

    /***********************************************************

    Q        如何产生和配置清单文件(Manifest.xml)?

    清单文件在整个更新过程非常重要。在更新的过程中这个清单会被Downloader从服务器上下载到本地,由Updater进行解析并判断是否有更新。如果有更新,Downloader会根据清单的内容,从服务器上下载相应的文件,Validator会根据清单中的签名对清单进行校验。下面是清单文件的例子,可以看出清单中的信息包括清单本身的签名,可用的应用版本号和位置,文件列表和签名,后处理器的名称等。

    注意:如果采用了RSA加密签名,则不可以手动改变此清单。此清单应由相应工具产生并用私有密钥进行签名。

    <ServerApplicationInfo signature="hPPVuZQAo95scW8vozlwho0Qny+eEdfbI4vqBbYyqfKaTYnigY5k83XHvkVyrPlLFGcUqIezGiKWkFq7X49ZryiIWyzWi3LEnltTy3xGBTAMvTekRfik0VFjiHVyQ9Fwz5DTKxhRWqmfJqAHiEM3Bj2JGJxTNvynbRFHjw0+RWM=">

      <availableVersion>1.0.0.0</availableVersion>

    <updateLocation>http://localhost/HISClinicWebDeploy/1.0.0.0/</updateLocation>

    <files>

      <file name="BLL.dll" signature="eAfVF1W3+k7CWBP67EJddtJd8b02ZE3N3R02QRdGw1VO5iluUEK22aCydC9kxOwEYPo4CWmxW4QMalSSSdv4h4TkPU1QGWB9i7Cs72pmWxMaKBN19WkFIgQr588lf+cCqRCBOdn7NVapXCwK6hLARcEhpWG/EeN3tAf/zSfRr8A=" /> 

      <file name="HISClinic.exe" signature="ojYnuA9kby/hlJOtLlsDglQT30Qn1/i1X3dvZMRjn+fZ0Tr0LjmBISOR0GgHxlHEexOzkyhjgJy3diVbhCbt4ucnxaN+B/ei2oBfW6Xt0wx25ywuGpo9tLuzwaUj9b9eAQ02Sj9eHY2YvKo0pSrOye9yoCYdl/fZhDj2WKhPcs4=" />

      <file name="HISClinic.exe.config" signature="aP0sXIqEC0FeDUHzPQ3EiregL9r8Y5CdtMP0es1rEW0Cx++iPPAJK8t1HBdE+FOGmQ2URwgUFZNzlm8sTw5yIM+mwSdo/MD8irICv2H/v980JbwcUY4vaPdl5+14PJPXRK+XVOk6s4tigw44qHbu8hu/geh7YvYrDVCfYOdbFIo=" />

      <file name="Microsoft.ApplicationBlocks.ApplicationUpdater.dll" signature="evasZb0Vd4k4AHQgZbsxubVMEDQPgxSn9YznyuPzFV87gMyJNNMzYeaAfJhwQWBga1aWO/CfwF1UectXsgQ4N0kziK3Nk4NvJBZzP5dkxh5zHnTvMgPTeyES3knQoKbUvHSyzEfxKYP4PlmJQXtupBYDzUe72C/sEkQR+obq/EY=" />

      .......

      <file name="PostProcessor.dll" signature="KsPcHLW/RJW5ohs3RT4FCyALTqoUDBHknhSQguZ8l0A95746qb5bQbbYjYMuNkGsLJPomsh0fytpld7oXhtaTksaCelRRTOnVXNjXY1Ev7BXD8Ph1GHPWopdQrQqHYRGEorCjGWx2rCpLvpu+xgFcP+jLCllCqJrWhz7wMOvY68=" />

      </files>

      <postProcessor type="PostProcessor.Processor" assembly="PostProcessor, Version=1.0.1796.1348, Culture=neutral, PublicKeyToken=null" name="PostProcessor.dll" />

    </ServerApplicationInfo>

     

    清单可用采用UAB自带的工具ManifestUtility.exe产生,如下图所示:

    Q        如何产生和配置App.Config文件?

    App.Config文件决定了在客户运行的应用版本和位置,其内容如下。其中最关键的appFolderName节点,此路径应为程序的安装路径,此文件应该在客户端初次安装时生成并置于应用的根目录下。

    <?xml version="1.0" encoding="utf-8"?>

    <configuration>

      <configSections>

        <section name="appStart" type="Microsoft.ApplicationBlocks.ApplicationUpdater.AppStart.ConfigSectionHandler,AppStart" />

      </configSections>

      <appStart>

        <ClientApplicationInfo>

          <appFolderName>D:\PROGRA~1\Winarray\HISDemo\HISClient\2.0.0.0</appFolderName>

          <appExeName>HISClinic.exe</appExeName>

          <installedVersion>2.0.0.0</installedVersion>

          <lastUpdated>2004-12-01T01:05:01.6490969+08:00</lastUpdated>

        </ClientApplicationInfo>

      </appStart>

    </configuration>

    Q        如何产生和配置HISDemo.exe.config文件?

    HISDemo.exe.config文件主要说明了应用使用UAB的情况和配置,对于使用RSA加密签名的文件,公钥存于此文件中。另外,在本应用中Sql的连接字符串也存于此文件中。如Sql服务器配置有改动,只需要改写此文件中的相应信息即可。

    <?xml version="1.0" encoding="utf-8"?>

    <configuration>

      <configSections>

        <section name="appUpdater" type="Microsoft.ApplicationBlocks.ApplicationUpdater.UpdaterSectionHandler,Microsoft.ApplicationBlocks.ApplicationUpdater" />

        <section name="exceptionManagement" type="Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManagerSectionHandler,Microsoft.ApplicationBlocks.ExceptionManagement" />

      </configSections>

      <appUpdater>

        <UpdaterConfiguration>

          <polling type="Seconds" value="60" />

          <logListener logPath="D:\PROGRA~1\Winarray\HISDemo\HISClient\UpdaterLog.txt" />

          <!--  ****************    BITS DOWNLOADER    ****************  -->

          <downloader type="Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSDownloader" assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" />

          <!--  ****************    THE RSA KEY HASHING VALIDATOR    ****************       -->

          <validator type="Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.RSAValidator" assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">

            <key>

              <RSAKeyValue>

                <Modulus>oslBz4MuFil9QKi3zkuqgsl8U7ppPQgCShDvb1D5dQTthlyo+dZ7wG7YEysxgm4P1ofr29muQIdjYRwhn7afvH1VgVahOLxVWsQm2rqNWbEZ9OV3UMFTf0P3erFiqxatDMiK65ayLmHXp0YM0zwxpm+ekQ8jm3Zg9ac0HePZsIk=</Modulus>

                <Exponent>AQAB</Exponent>

              </RSAKeyValue>

            </key>

          </validator>

          <application name="HISClinic" useValidation="true">

            <client>

              <baseDir>D:\PROGRA~1\Winarray\HISDemo\HISClient</baseDir>          <xmlFile>D:\PROGRA~1\Winarray\HISDemo\HISClient\AppStart.exe.config</xmlFile>

              <tempDir>D:\PROGRA~1\Winarray\HISDemo\HISClient\DownloadFiles</tempDir>

            </client>

            <server>

              <xmlFile>http://localhost/HISClinicWebDeploy/ServerManifest.xml</xmlFile>     <xmlFileDest>D:\PROGRA~1\Winarray\HISDemo\HISClient\ServerManifest.xml</xmlFileDest>

              <maxWaitXmlFile>60000</maxWaitXmlFile>

            </server>

          </application>

        </UpdaterConfiguration>

      </appUpdater>

    </configuration>

     <exceptionManagement mode="on" />

      <appSettings>

        <add key="DBConnectionString" value="uid=sa;pwd=;data source=(local);initial catalog=HisClinic" />

      </appSettings>

    Q        如何将安装路径写入配置文件?

    为了能使UAB正常的工作,在配置文件HISClinic.exe.config中需要指明程序安装的路径。由于客户端可能安装在任意的路径下,为此在应用的文件安装或下载以后需要再将安装路径写入配置文件,确保应用的正常工作。

    在应用程序的文件完成拷贝和下载后,需要运行如下代码,实现下列任务:通过Reflection.Assembly取得当前运行路径以及更改HISClinic.exe.config配置

    参考代码:       HISClinic\HISDemo\PostProcessor\Processor.cs

    /***********************************************************

    public class Processor:IPostProcessor

    {

    public Processor()

        {

            //

            // TODO: 在此处添加构造函数逻辑

            //

        }

        /// <summary>

        /// 实现IPostprocessor.Run接口方法

        /// 更改下载程序配置信息

        /// </summary>

        public  void Run()

    {

            String p=Path.GetDirectoryName

    (System.Reflection.Assembly.GetExecutingAssembly().Location);

    DirectoryInfo dir=new DirectoryInfo(p);

    Config.ConfigFile config=new

    Config.ConfigFile(Path.Combine(p,@"HISClinic.exe.config"));

            config.ChangePath("HISClinic",dir.Parent.FullName);

        }

        public  void Dispose(){}

    }

    /***********************************************************

    Q        如何设定更新检测的时间?

    应用程序如需要设定更新检测时间,可以通过设置HISClinic.exe.configpolling节点属性以及设定UABUpdaterConfiguration.Instance来实现

    参考代码: HISClinic\HISDemo\HIClinic\SelfUpdater.CS;

                       HISClinic\HISDemo\ChangePath\Config.CS;

     

    /***********************************************************

    /// <summary>

    /// 设置Polling间隔

    /// </summary>

    public int Interval

    {

    set

    {

            SavePollingIntoConfigFile(value);

        }

        get

    {

            return GetPollingInterval();

        }

    }

    /// <summary>

    /// 保存更新间隔,单位(秒)

    /// </summary>

    /// <param name="interval"></param>

    private void SavePollingIntoConfigFile(int interval)

    {

    Config.ConfigFile configfile=new

    Config.ConfigFile(System.Reflection.Assembly.

    GetExecutingAssembly().Location+".config");

    //修改配置文件  

    configfile.UpdateInterval=interval;

    //修改UAB实例

        UpdaterConfiguration.Instance.Polling.Value=interval.ToString();

        UpdaterConfiguration.Instance.Polling.Type=PollingType.Seconds;

    }

    /// <summary>

    /// 获取更新间隔,单位(秒)

    /// </summary>

    /// <returns></returns>

    private int GetPollingInterval()

    {

    Config.ConfigFile configfile=new

    Config.ConfigFile(System.Reflection.Assembly.GetExecutingAssembly().Loca

    tion+".config");

        return configfile.UpdateInterval;

    }

    /***********************************************************

    Q        如何实现强制的手动即时更新?

    应用程序如果需要通过界面控制实现强制的手动即时更新,可以通过以下方式实现。首先调用ApplicationUpdateManager.StopUpdater()停止更新,然后重新实例化ApplicationUpdateManager,并通过调用StartUpdater()实现更新

    参考代码:       HISClinic\HISDemo\HIClinic\selfUpdater.CS

    /***********************************************************

    /// <summary>

    /// 重新开始更新

    /// </summary>

    public void ReStartUpdate()

    {

        updater=null;

        InitUpdater();

        updater.StartUpdater();

    }

    /***********************************************************

    Q        如何设定更新日志路径以及设定是否需要保留更新日志?

    默认情况下,UAB会将更新日志存放在应用安装的根目录下,并且每次运行运用都会产生一个新的日志。这种机制会在客户端留下大量的日志文件。如果需要设定更新日志路径以及设定是否需要保留更新日志,需要更改UAB配置文件和对应实例以及EMAB配置文件

    参考代码:       HISClinic\HISDemo\HIClinic\SelfUpdater.CS;

    HISClinic\HISDemo\ChangePath\Config.CS;

    /***********************************************************

    /// <summary>

    /// 设置日志路径

    /// </summary>

    /// <param name="path"></param>

    public void SetLogPath(string path)

    {

        XmlDocument doc=new XmlDocument();

        doc.Load(configfilepath);

        XmlNodeList nodes=doc.GetElementsByTagName("logListener");

        if(path.Length>0)

        {//设置UAB日志标志

            XmlNode node=null;

            if(nodes.Count>0)   node=nodes[0];

            else

            {

                node=doc.CreateElement("logListener");

                XmlAttribute attr=doc.CreateAttribute("logPath");

                node.Attributes.Append(attr);                  

    doc.SelectSingleNode("configuration/appUpdater/UpdaterConfigurat

    ion").AppendChild(node);

            }

            node.Attributes["logPath"].Value=path; 

        }  

        else

        {//设置EMAB日志标志

        XmlNode node=doc.SelectSingleNode

                ("configuration/appUpdater/UpdaterConfiguration/logListener");

        if(node!=null)

        node.ParentNode.RemoveChild(node);

        }

       

        SetEMABLogPulish(path.Length>0,doc);

        doc.Save(configfilepath);

    }

    /***********************************************************

    Q        如何实现使用任意协议(http, ftp…)进行下载?

    UAB采用Windows自带的BITS服务进行文件的下载,如需要采用任意协议或是自定义的下载器进行下载,开发自定义的下载器,并实现IDownloader接口即可

    如何删除客户端操作系统上不必要的较早版本的文件备份

    默认情况下UAB会保留较早版本的文件备份,可以通过实现IPostprocessor接口,开发简单代码,在应用更新成功后,对不必要文件进行删除。

    Q        如何在应用安装的同时自动的导入数据库?

    将要安装的数据库文件.mdf拷贝到[数据库安装路径]通过OSQL命令调用如下的T-SQL 脚本。

    EXECUTE sp_attach_db @dbname    = N'<database_name, sysname, test_db>',

                       @filename1 = N'<filename1, nvarchar(260), [数据库安装路径]\*.mdf>',

                       @filename2 = N'<filename2, nvarchar(260), [数据库安装路径]\*.mdf >'

    GO

    文件的拷贝和OSQL命令的调用可以通过安装程序进行,从而实现数据库的自动安装。

    下载例子

  • 相关阅读:
    [HNOI2007]最小矩形覆盖
    [HAOI2008]下落的圆盘
    JSON相关 JSON在线解析 JSON压缩转义工具 JSON着色工具 JSON 在线格式化工具 在线XML/JSON互相转换工具 XML、JSON在线转换
    速度竟差9倍!6款32GB USB3.0优盘横评
    Linux 中用 dd 命令来测试硬盘读写速度
    CrystalDiskMark v7.0.0h中文版
    个人觉得,不单是教育缺失的问题,贫穷才是真像。贫穷分
    就算是3.0的U盘,写入速度10M及以下也是正常的,U盘用很差的闪存颗粒的话就算10Gbps的USB3.1也是很慢的。
    USB历代标准及接口发展
    测试 USB 存储设备读写性能(Mb/s),平均读写速度等
  • 原文地址:https://www.cnblogs.com/ynlxc/p/265252.html
Copyright © 2011-2022 走看看