写一个更新小程序,更新时调用小程序,小程序下载完新程序后开始替换要更新的主程序,先检测要更新的主程序是否正在运行,如果运行就关掉主程序,备份主程序,提换主程序过程大慨就是这样了 从web服务器下载这个你就自己去查资料了

解决方案 »

  1.   

    在程序集中可以设置版本,可以直接得到版本号,或查询注册表得到,
    你可以做一个webservice,返回最新的版本号,程序运行时定时查询webservice,然后下载,更新cdknet(VC++.NET)说的是以前的程序,现在.net已经没有dll的问题了,就是说每个版本有单独的目录存放dll,不会有冲突的,当然需要你程序只需要下载dll文件就可以完成更新。
      

  2.   

    看看下面这篇文章,应该有帮助在WinForm中使用Web Services 来实现 软件 自动升级
    http://dev.csdn.net/article/28/article/28/28787.shtm
      

  3.   

    1、在服务器上建立虚拟目录appUpdate
    2、设置升级配置文件UpdateConfig.xml内容,放到虚拟目录appUpdate下:
    格式:moduleName为动态链接库名称,vertion为当前版本号,appUrl为提供下载的地址
    例子:
    <root>
    <module>
    <moduleName>Module1.dll</moduleName>
    <vertion>1.0.0.1</vertion>
    <appUrl>http://localhost/appUpdate/Module1.dll</appUrl>
    </module>
    <module>
    <moduleName>Module2.dll</moduleName>
    <vertion>1.0.0.1</vertion>
    <appUrl>http://localhost/appUpdate/Module2.dll</appUrl>
    </module>
    <module>
    <moduleName>ZiModule2ReportPrint.dll</moduleName>
    <vertion>1.0.0.1</vertion>
    <appUrl>http://localhost/appUpdate/ZiModule2ReportPrint.dll</appUrl>
    </module>
    </root>
    3、WebService,部署到appUpdate虚拟目录下:
    [WebMethodAttribute]
    public System.Xml.XmlDocument AppUpdateVertion()
    {
    System.Xml.XmlDocument xml = new System.Xml.XmlDocument();
    xml.Load(CurrentPath("/appUpdate") + @"\UpdateConfig.xml");
    return xml;
    }
    private string CurrentPath(string virtualPath)
    {
    return HttpContext.Current.Server.MapPath(virtualPath);
    }3、升级版本判断

    /// <summary>
    /// 从webServiceAddress中下载新版本
    /// </summary>
    /// <param name="desPath">新版本的存放目录</param>
    /// <param name="webServiceAddress">webService的网址</param>
    private void VersionCheck(string desPath,string webServiceAddress)
    {
    try
    {
    #region 查看文件和目录
    if(!desPath.EndsWith(@"\"))
    desPath += @"\"; if(!System.IO.Directory.Exists(desPath))
    {
    System.IO.Directory.CreateDirectory(desPath);
    } string tempPath = desPath + @"tempDesPathCache\"; if(System.IO.Directory.Exists(tempPath))
    {
    System.IO.Directory.Delete(tempPath,true);
    System.IO.Directory.CreateDirectory(tempPath);
    }
    else
    System.IO.Directory.CreateDirectory(tempPath); if(!System.IO.File.Exists(desPath + "UpdateConfig.xml"))
    {
    System.Xml.XmlDocument updateConfig = new System.Xml.XmlDocument();
    updateConfig.LoadXml(@"<root></root>");
    updateConfig.Save(desPath + "UpdateConfig.xml");
    }
    #endregion AppUpdate.AppUpdate appUpdate = new Test.AppUpdate.AppUpdate();
    appUpdate.Url = webServiceAddress;
    System.Xml.XmlDocument serverXmlDoc = appUpdate.AppUpdateVertion();
    System.Xml.XmlDocument localXmlDoc = new System.Xml.XmlDocument();
    localXmlDoc.Load(desPath + "UpdateConfig.xml");
    bool newVersionExist = false;
    bool moduleExist = false;
    System.Xml.XmlNode serverNode0 = serverXmlDoc.ChildNodes[0];
    System.Xml.XmlNode localNode0 = localXmlDoc.ChildNodes[0];
    foreach(System.Xml.XmlNode serverNode in serverNode0)
    {
    moduleExist = false;
    foreach(System.Xml.XmlNode localNode in localNode0)
    {
    //找到对应模块
    if(localNode.ChildNodes[0].InnerText == serverNode.ChildNodes[0].InnerText)
    {
    moduleExist = true;
    //版本号判断
    if(localNode.ChildNodes[1].InnerText.CompareTo(serverNode.ChildNodes[1].InnerText) < 0)
    {
    newVersionExist = true;
    DownloadFile(serverNode.ChildNodes[2].InnerText,tempPath + serverNode.ChildNodes[0].InnerText);
    }
    break;
    }
    }
    //没找到对应模块
    if(false == moduleExist)
    {
       DownloadFile(serverNode.ChildNodes[2].InnerText,tempPath + serverNode.ChildNodes[0].InnerText);
    }
    }
    //写入新UpdateConfig.xml升级完毕后替换
    if(newVersionExist)
    {
    serverXmlDoc.Save(tempPath + "UpdateConfig.xml");
    if(DialogResult.Yes == MessageBox.Show("有新版本,升级否","提示",MessageBoxButtons.YesNo))
    {
    string[] dirs = System.IO.Directory.GetFiles(tempPath, "*.*");
    string fileName;
    foreach (string dir in dirs)
    {
    fileName = ((dir.Split(Convert.ToChar(@"\")))[dir.Split(Convert.ToChar(@"\")).Length - 1]);
    if(System.IO.File.Exists(desPath + fileName))
    {
    //TODO:可以支持备份以前版本
    System.IO.File.Delete(desPath + fileName);
    }
    //TODO:如果系统正在运行,您得停止系统,至于如何停止,也许可以使用System.Diagnostics.Process
    System.IO.File.Move(dir,desPath + fileName);
    }
    MessageBox.Show("升级完毕");
    }
    else
    {
    //TODO:可以支持重新提示升级
    }
    }
    }
    catch(Exception ex)
    {
    throw new Exception("升级失败,原因是:" + ex.Message,ex);
    }
    }4、下载文件:
    private void DownloadFile(string source,string fileName)
    {
    try
    {
    System.Net.WebClient myWebClient = new System.Net.WebClient();
    myWebClient.DownloadFile(source,fileName);
    }
    catch(Exception ex)
    {
    throw new Exception("下载失败,原因是:" + ex.Message,ex);
    }
    }
    5、客户端调用:
    string path =Application.StartupPath;
    VersionCheck(path,"http://localhost/AppUpdate/AppUpdate.asmx")
      

  4.   

    我以前是这样做的 
    将主程序编译成Dll,再写一个UpDate程序,功能很简单,就是到数据库里面查询目标程序的最新版本号,Update程序同时获取本机的Dll的版本号,进行比较,确定是否从数据库下载Dll , 最后启动程序
    简单提示
    数据库部分:
    create table Apps
    (
       APPS_NAME       varchar(30)  not null, --程序名称
       APPS_VER        varchar(30)  not null, --程序版本
       APPS_DATA       RAW          not null, --保存程序数据
    );
    程序部分:
       1.获取最新的程序版本号通过查询数据库得到
       2.获取本机程序版本号这样得到
           string sFileName = System.Environment.CurrentDirectory + "\\MyApp.dll";
           if(File.Exists(sFileName))
    {
       Assembly assLocal = Assembly.LoadFile(sFileName);
       AssemblyName assLocalName = assLocal.GetName();
                string sLocalVer= assLocalName.Version;
              } 
       3.比较两个版本号
       4.下载程序,从数据库里面将APP_DATA查出
             byte[] bData = (byte[])(oDs.Tables[0].Rows[0][0]);
       5.将byte[]覆写本机的MyApp.dll , 这样最新程序就被下载了
       6.最后运行最新程序
    Assembly assLocal = Assembly.LoadFile(sFileName);
             Form frm = (Form)assLocal.CreateInstance("MyApp.MainForm");//这里的命名空间一定要注意,要不然会出错
             frm.Visble = true;
             //下面再将那个UpDate窗体隐藏即可
      

  5.   

    谢谢各位,我比较想通过Http下载方式使用BITS或者Updater Application Block,各位能否有比较好的DEMO?
      

  6.   

    无间道III(终极无间))说的不错.
    我看过AppUpdater.dll的源程序,它里面还包含了数字验证, 为了防止被欺骗,下载错误的程序集破坏本低地数据或成为木马。
      

  7.   

    使用的例子可以看,
    TaskVision
    http://www.windowsforms.net/Applications/application.aspx?PageID=20&tabindex=8
    rssbandit
    http://sourceforge.net/projects/rssbandit/
      

  8.   

    又遇到问题啦XML转换出问题
    在WebService中,申明为
    public System.Xml.XmlDocument GetUpdateData()
    {
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.Load(Server.MapPath("update.xml")); return doc;
    }为啥在前台调用,这个System.Xml.XmlDocument 类型就变为System.Xml.XmlNode了?使用了转换,System.Xml.XmlDocument doc = (System.Xml.XmlDocument)MS.GetUpdateData()
    总是告诉我转换错误System.Xml.XmlNode如何转换为System.Xml.XmlDocument ???
      

  9.   

    你说的转换操作不会存在。
    下面是正确的。
    public System.Xml.XmlDocument GetUpdateData()
    {
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.Load(Server.MapPath("update.xml")); return doc;
    }
    XmlDocument doc = MS.GetUpdateData();
    这句没有错。
    告诉你转换错误是doc.Load(Server.MapPath("update.xml"));这一句有问题,抛出异常,
    你的update.xml文件不符和xml文件格式,请检查一下。
      

  10.   

    Updater Application Block实践
    ---------------------------------------------------------------Step #1 Install the Application Blocks                              安装自动更新组件Download the Updater Application Block from Microsoft.Step #2 Add the Code and References to Your Project:  添加代码和引用到工程Add the following projects to the solution containing your Winforms project :把以下工程添加到你的解决方案Microsoft.ApplicationBlocks.ApplicationUpdater
    Microsoft.ApplicationBlocks.ApplicationUpdater.Interfaces
    Microsoft.ApplicationBlocks.ExceptionManagement
    Microsoft.ApplicationBlocks.ExceptionManagement.InterfacesThey should be located in the following folder, if you've accepted the defaults 默认的安装位置在C:\Program Files\Microsoft Application Blocks for .NET\Updater\Code\CS\Microsoft.ApplicationBlocks.UpdaterReference the following projects from within your Winforms Project 在工程中添加引用Microsoft.ApplicationBlocks.ApplicationUpdater
    Microsoft.ApplicationBlocks.ApplicationUpdater.Interfaces
    Microsoft.ApplicationBlocks.ExceptionManagementAdd the following namespaces to your form's .cs file.using System.Runtime.InteropServices;
    using System.Runtime.Serialization;
    using System.Threading;
    using System.Diagnostics;
    using System.IO;
    using System.Xml;using Microsoft.ApplicationBlocks.ApplicationUpdater;  工程要引用其中的类Then add the application updater code located here to your code.  You'll need to call InitializeAutoUpdate() from your MainForm's Initialize method.把以下代码添加到工程首页。Step #3 Create your Application's Deployment Directory Structure and Configure AppStart.exe 创建发布目录并配置配置文件Create a folder for your client installation.  For example purposes, we'll use the following directory: 创建客户端安装目录,如:C:\Program Files\YourApp\1.0.0.0\Now copy the AppStart.exe and AppStart.exe.config into the root directory like so: 把以下两个文件拷贝到安装的根目录(C:\Program Files\YourApp) C:\Program Files\YourApp\AppStart.exe
     C:\Program Files\YourApp\AppStart.exe.configNote: You can find these two files in the “C:\Program Files\Microsoft Application Blocks for .NET\Updater\Code\CS\Microsoft.ApplicationBlocks.Updater\AppStart\bin\Debug“ directory.  
      

  11.   


    Step #4 Modify the AppStart.exe.config File 修改配置文件AppStart.exe.config Appstart.exe.config将负责启动你的程序。Modify this config file to match the current version like so: 按照你程序的当前版本配置此文件: 
    <appStart>
      <ClientApplicationInfo>
        <appFolderName>C:\Program Files\YourApp\1.0.0.0</appFolderName>
        <appExeName>YourAppName.exe</appExeName>
        <installedVersion>1.0.0.0</installedVersion>
        <lastUpdated>2004-06-10T15:33:17.3745836-04:00</lastUpdated>
      </ClientApplicationInfo>
    </appStart> Step #5: Create Your Public and Private Keys 创建公匙和私匙Run the ManifestUtility "C:\Program Files\Microsoft Application Blocks for .NET\Updater\Code\CS\Microsoft.ApplicationBlocks.Updater\ManifestUtility\bin\Debug\ManifestUtility.exe"Choose “File..Generate Keys”  You will be prompted to save the following keys: PublicKey.xml and PrivateKey.xml  You'll be using these keys in the next steps.  From what I can tell it's best to create these keys once, because you'll need to reference these RSA public and private keys in a couple of places.  You'll want to keep your keys in a safe place, because you'll need them when pushing new updates. 此工具生成成对的公匙和私匙。Step #6 Create Your IIS Virtual DirectoryCreate a directory on your WebServer to house your updates.  You will end up with two things in this directory 1) a ServerManifest.xml file which will contain the latest version information, and 2) your new application directory. Within this directory, create a directory to house your new application version.  So, for our example, we'll create the directories, C:\Inetpub\AppUpdates  and C:\Inetpub\AppUpdates\1.0.0.1Use IIS Manager to create a virtual directory pointing to this physical directory.  Remember your URL, as you will need it in an upcoming step.  You will have to enable directory browsing for this virtual directory. 创建IIS的虚拟目录,在此存放你的新程序版本,例如: C:\Inetpub\AppUpdates          包括你新版本程序的信息的配置文件将放在此目录 C:\Inetpub\AppUpdates\1.0.0.1  新版本的程序放在此目录Step #7. Configure Your Version 1.0.0.0 App.config File  配置你程序的配置文件(你的程序名.config即完整程序名加.config例如:App01.exe.config 程序将默认寻找与其同名的.config配置文件,{DLL没有此项功能})Here, we'll need to add a few things.  First, we need to add a configSections element to define our appUpdater section:
    <configSections>
      <section name="appUpdater" type="Microsoft.ApplicationBlocks.ApplicationUpdater.UpdaterSectionHandler,Microsoft.ApplicationBlocks.ApplicationUpdater" />
    </configSections>Next we need to add the Version key to our appsettings key, we're first going to set our local versoin to 1.0.0.0, so that we can test the auto-update to version 1.0.0.1<appSettings>
      <add key="VERSION" value="1.0.0.0" />    注意版本号一定要与程序的设定的版本号匹配
    </appSettings>Finally, add the appUpdater section to your config file.  I've put brackets where you need to edit the values.  You can just copy the <RSAKeyValue> element from the PublicKey.xml file that you created in the previous step. 把刚才生成的公匙填到配置文件的相应位置,(以下[]中)。<appUpdater>
      <UpdaterConfiguration>
       <polling type="Seconds" value="120" />
       <logListener logPath="C:\Program Files\YourApp\UpdaterLog.txt" />
       <downloader type="Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSDownloader" 
    assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
       <validator type="Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.RSAValidator" assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">
      <key>
       <RSAKeyValue>
      <Modulus>[YOUR MODULUS KEY]</Modulus>
      <Exponent>[YOUR EXPONENET]</Exponent>
      </RSAKeyValue>
      </key>
      </validator> 
      <application name="[YOUR APP NAME]" useValidation="true">  此处是你程序的名称,如App01,无需后缀
        <client>
          <baseDir>C:\Program Files\YourApp</baseDir>
          <xmlFile>C:\Program Files\YourApp\AppStart.exe.config</xmlFile>
          <tempDir>C:\Program Files\YourApp\temp</tempDir>
        </client>
        <server>
         <xmlFile>http://[YOUR URL]/ServerManifest.xml</xmlFile>
         <xmlFileDest>C:\Program Files\YourApp\ServerManifest.xml</xmlFileDest>
         <maxWaitXmlFile>60000</maxWaitXmlFile>
        </server>
      </application> 
     </UpdaterConfiguration>
     </appUpdater>Step #8 Deploy Version 1.0.0.0   发布版本1.0.0.0
    Version your app.  You do this by setting the version attribute of your app's AssemblyInfo.cs file.   修改你程序的版本号(在AssemblyInfo.cs中)[assembly: AssemblyVersion("1.0.0.0")]Build the Application and copy version 1.0.0.0 to your program file's 1.0.0.0 directory. “C:\Program Files\YourApp\1.0.0.0“将版本1.0.0.0拷贝到你的客户端安装目录(注意,在版本号下1.0.0.0)At this point, you should be able to run AppStart.exe.  The update process should fail, since we haven't deployed the ServerManifest XML file which tells our app that there's a new version available.  You can inspect the log files that should be created in your C:\Program Files\YourApp\ directory.Step #9 Buld Version 1.0.0.1   创建新版本1.0.0.1 将新版本拷贝到你的发布目录,在step #6创建的C:\Inetpub\AppUpdates\1.0.0.1下 注意同时拷贝到发布目录的还应该有:配置文件 App01.exe.config 因为可能找不到微软的组件,以下几个文件也一同拷贝,(否则升级时可能会报错system.io.filenotfoundException的错误,找不到相应的文件) Microsoft.ApplicationBlocks.ApplicationUpdater.dll
    Microsoft.ApplicationBlocks.ApplicationUpdater.Interfaces.dll
    Microsoft.ApplicationBlocks.ExceptionManagement.dll
    Microsoft.ApplicationBlocks.ExceptionManagement.Interfaces.dll注意以上文件都在版本号的目录下,C:\Inetpub\AppUpdates\1.0.0.1Step #10 Create Your Server Manifest File  生成服务端的升级说明文件This should be the last step.  Any changes you make to the .config files from this point on will require repeating this step.  To do this: Launch the ManifestUtility program again.  再次用工具 ManifestUtility (step #5中的工具) 
    Choose the 1.0.0.1 directory from the “Update files folder“ chooser.  选择新版本程序的目录(注意是带版本号的目录) 
    Enter the URL of the update location.  新版本的HTTP的址(注意带版本号的目录) 
    Enter version 1.0.0.1  新的程序版本号 
    Open your PrivateKey.xml file created earlier. Key处添加你刚才生成的私匙 
    Choose the validator class   选择校验类为RSA的“Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.RSAValidator” 
    Click CreateManifest, and save the ServerManifest.xml file to your virtual server directory.  生成新版本说明文件,存放在虚拟目录下(注意是不带版本号的,C:\Inetpub\AppUpdates\)
    生成的ServerManifest.xml文件中说明了要升级的文件的内容,1.0.0.1下的内容都将下载。参考图如下:
      

  12.   


    --------------------------------------------
    step 2 的代码
    #region Auto-Update Stuff

    private ApplicationUpdateManager _updater = null;
    private Thread _updaterThread = null;
    private const int UPDATERTHREAD_JOIN_TIMEOUT = 3 * 1000;private delegate void MarshalEventDelegate( object sender, UpdaterActionEventArgs e );private void InitializeAutoUpdate()
    {
    //  hook ProcessExit for a chance to clean up when closed peremptorily
    AppDomain.CurrentDomain.ProcessExit +=new EventHandler(CurrentDomain_ProcessExit); //  make an Updater for use in-process with us
    _updater = new ApplicationUpdateManager(); //  hook Updater events
    _updater.DownloadStarted +=new UpdaterActionEventHandler( OnUpdaterDownloadStarted );
    _updater.FilesValidated +=new UpdaterActionEventHandler( OnUpdaterFilesValidated );
    _updater.UpdateAvailable +=new UpdaterActionEventHandler( OnUpdaterUpdateAvailable );
    _updater.DownloadCompleted +=new UpdaterActionEventHandler(OnUpdaterDownloadCompleted); //  start the updater on a separate thread so that our UI remains responsive
    _updaterThread = new Thread( new ThreadStart( _updater.StartUpdater ) );
    _updaterThread.Start(); //  get version from config, set caption correctly
    string version = System.Configuration.ConfigurationSettings.AppSettings["version"];
    this.Text = this.Text + String.Format(" v. {0}", version);
    }private void CurrentDomain_ProcessExit(object sender, EventArgs e)
    {
    StopUpdater();
    }
    private void StopUpdater()
    {
    //  tell updater to stop
    _updater.StopUpdater();
    if( null != _updaterThread )
    {
    //  join the updater thread with a suitable timeout
    bool isThreadJoined = _updaterThread.Join( UPDATERTHREAD_JOIN_TIMEOUT );
    //  check if we joined, if we didn't interrupt the thread
    if( !isThreadJoined )
    {
    _updaterThread.Interrupt();
    }
    _updaterThread = null;
    }
    }/// <summary>
    /// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM.  It takes the same 
    /// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
    /// </summary>
    /// <param name="sender">marshalled reference to the original event's sender argument</param>
    /// <param name="e">marshalled reference to the original event's args</param>
    private void OnUpdaterDownloadStartedHandler( object sender, UpdaterActionEventArgs e ) 
    {
    Debug.WriteLine("Thread: " + Thread.CurrentThread.GetHashCode().ToString()); Debug.WriteLine(String.Format( "  DownloadStarted for application '{0}'", e.ApplicationName ));
    }
    /// <summary>
    /// Event handler for Updater event.  This event is fired by the originating thread from "inside" the Updater.  While it is
    /// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.  
    /// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
    /// mechanism.
    /// </summary>
    /// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
    /// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param>
    private void OnUpdaterDownloadStarted( object sender, UpdaterActionEventArgs e )

    //  using the synchronous "Invoke".  This marshals from the eventing thread--which comes from the Updater and should not
    //  be allowed to enter and "touch" the UI's window thread
    //  so we use Invoke which allows us to block the Updater thread at will while only allowing window thread to update UI
    Debug.WriteLine( String.Format( "[OnUpdaterDownloadStarted]Thread: {0}", Thread.CurrentThread.GetHashCode().ToString()) );
    this.Invoke( 
    new MarshalEventDelegate( this.OnUpdaterDownloadStartedHandler ), 
    new object[] { sender, e } );
    }
    /// <summary>
    /// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM.  It takes the same 
    /// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
    /// </summary>
    /// <param name="sender">marshalled reference to the original event's sender argument</param>
    /// <param name="e">marshalled reference to the original event's args</param>
    private void OnUpdaterFilesValidatedHandler( object sender, UpdaterActionEventArgs e )
    {
    Debug.WriteLine(String.Format("FilesValidated successfully for application '{0}' ", e.ApplicationName));

    //  ask user to use new app
    DialogResult dialog = MessageBox.Show( 
    "Would you like to stop this application and open the new version?", "Open New Version?", MessageBoxButtons.YesNo );
    if( DialogResult.Yes == dialog )
    {
    StartNewVersion( e.ServerInformation );
    }
    }/// <summary>
    /// Event handler for Updater event.  This event is fired by the originating thread from "inside" the Updater.  While it is
    /// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.  
    /// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
    /// mechanism.
    /// </summary>
    /// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
    /// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param>
    private void OnUpdaterFilesValidated( object sender, UpdaterActionEventArgs e )
    {
    //  using the asynchronous "BeginInvoke".  
    //  we don't need/want to block here
    this.BeginInvoke( 
    new MarshalEventDelegate( this.OnUpdaterFilesValidatedHandler ),
    new object[] { sender, e } );
    }
      

  13.   

    to  zhzuo(秋枫) 底下这个函数是写在WebService中的
    public System.Xml.XmlDocument GetUpdateData()
    {
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.Load(Server.MapPath("update.xml")); return doc;
    }在客户端作Web引用之后,new出一个MS的WebService,结果看到GetUpdateData的类型是XmlNode,而不是XmlDocument了,因此需要做转换,要不保存不了
      

  14.   

    /// <summary>
    /// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM.  It takes the same 
    /// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
    /// </summary>
    /// <param name="sender">marshalled reference to the original event's sender argument</param>
    /// <param name="e">marshalled reference to the original event's args</param>
    private void OnUpdaterUpdateAvailableHandler( object sender, UpdaterActionEventArgs e )
    {
    Debug.WriteLine("Thread: " + Thread.CurrentThread.GetHashCode().ToString()); string message = String.Format( 
    "Update available:  The new version on the server is {0} and current version is {1} would you like to upgrade?", 
    e.ServerInformation.AvailableVersion,  
    System.Configuration.ConfigurationSettings.AppSettings["version"] ) ; //  for update available we actually WANT to block the downloading thread so we can refuse an update
    //  and reset until next polling cycle;
    //  NOTE that we don't block the thread _in the UI_, we have it blocked at the marshalling dispatcher "OnUpdaterUpdateAvailable"
    DialogResult dialog = MessageBox.Show( message, "Update Available", MessageBoxButtons.YesNo ); if( DialogResult.No == dialog )
    {
    //  if no, stop the updater for this app
    _updater.StopUpdater( e.ApplicationName );
    Debug.WriteLine("Update Cancelled.");
    }
    else
    {
    Debug.WriteLine("Update in progress.");
    }
    }/// <summary>
    /// Event handler for Updater event.  This event is fired by the originating thread from "inside" the Updater.  While it is
    /// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.  
    /// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
    /// mechanism.
    /// </summary>
    /// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
    /// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param>
    private void OnUpdaterUpdateAvailable( object sender, UpdaterActionEventArgs e )
    {
    //  using the synchronous "Invoke".  This marshals from the eventing thread--which comes from the Updater and should not
    //  be allowed to enter and "touch" the UI's window thread
    //  so we use Invoke which allows us to block the Updater thread at will while only allowing window thread to update UI
    this.Invoke( 
    new MarshalEventDelegate( this.OnUpdaterUpdateAvailableHandler ), 
    new object[] { sender, e } );
    }
    /// <summary>
    /// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM.  It takes the same 
    /// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
    /// </summary>
    /// <param name="sender">marshalled reference to the original event's sender argument</param>
    /// <param name="e">marshalled reference to the original event's args</param>
    private void OnUpdaterDownloadCompletedHandler( object sender, UpdaterActionEventArgs e )
    {
    Debug.WriteLine("Download Completed.");}/// <summary>
    /// Event handler for Updater event.  This event is fired by the originating thread from "inside" the Updater.  While it is
    /// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.  
    /// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
    /// mechanism.
    /// </summary>
    /// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
    /// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param>
    private void OnUpdaterDownloadCompleted( object sender, UpdaterActionEventArgs e )
    {
    //  using the synchronous "Invoke".  This marshals from the eventing thread--which comes from the Updater and should not
    //  be allowed to enter and "touch" the UI's window thread
    //  so we use Invoke which allows us to block the Updater thread at will while only allowing window thread to update UI
    this.Invoke( 
    new MarshalEventDelegate( this.OnUpdaterDownloadCompletedHandler ), 
    new object[] { sender, e } );
    }
    private void StartNewVersion( ServerApplicationInfo server )
    {
    XmlDocument doc = new XmlDocument(); //  load config file to get base dir
    doc.Load( AppDomain.CurrentDomain.SetupInformation.ConfigurationFile ); //  get the base dir
    string baseDir = doc.SelectSingleNode("configuration/appUpdater/UpdaterConfiguration/application/client/baseDir").InnerText;
    string newDir = Path.Combine( baseDir, "AppStart.exe" ); ProcessStartInfo process = new ProcessStartInfo( newDir );
    process.WorkingDirectory = Path.Combine( newDir , server.AvailableVersion ); //  launch new version (actually, launch AppStart.exe which HAS pointer to new version )
    Process.Start( process ); //  tell updater to stop
    CurrentDomain_ProcessExit( null, null );
    //  leave this app
    Environment.Exit( 0 );
    }
      

  15.   

    Update.XML如下<?xml version="1.0" encoding="utf-8" ?> 
    <product>
     <version>1.0.1818.42821</version>
     <description>修正一些Bug</description>
     <filelist count="4" sourcepath="./update/">
      <item name="City.xml" size="">
       <value />
      </item>
      <item name="CaptureNET.exe" size="">
       <value />
      </item>
      <item name="DShowNET.dll" size="">
       <value />
      </item>
      <item name="Citys.xml" size="">
       <value />
      </item>
     </filelist>
    </product>谢谢JafyLiu(土豆) ,我将研究研究你提供的方法
      

  16.   

    得在webservice映射类中修改System.Xml.XmlNode为System.Xml.XmlDocument
      

  17.   

    得在webservice代理类中修改System.Xml.XmlNode为System.Xml.XmlDocument
    我也不知道为什么System.Xml.XmlDocument被.Net FrameWork自动修改为System.Xml.XmlNode
      

  18.   

    chenszhs(突破程序员) 如何修改啊?
      

  19.   

    ms-help://MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconcreatingwebserviceproxy.htm创建 XML Web services 代理请参见
    生成 XML Web services 客户端 | 发现 XML Web services | 为 XML Web services 创建客户端 | 浏览现有的使用 ASP.NET 创建的 XML Web services | 与 XML Web services 进行异步通信 | 从浏览器访问 XML Web services
    语言
    C#Visual Basic全部显示
    按照定义,可以使用行业标准协议(包括 SOAP)通过网络与 XML Web services 进行通信。也就是说,客户端和 XML Web services 使用 SOAP 消息进行通信,SOAP 消息将输入和输出参数封装为 XML。幸好对于 XML Web services 客户端来说,代理类处理将参数映射为 XML 元素,然后通过网络发送 SOAP 消息这些工作。只要存在服务说明并且该服务说明符合 Web 服务描述语言 (WSDL),就可以生成代理类。服务说明定义如何与 XML Web services 进行通信。使用服务说明,可以使用 Wsdl.exe 工具创建一个代理类。接着,XML Web services 客户端可以调用该代理类的方法,而该代理类又通过处理往返于 XML Web services 的 SOAP 消息,通过网络与 XML Web services 进行通信。由于代理类通过 Internet 与 XML Web services 通信,最好验证一下代理类的 Url 属性引用的是否是受信任的目标。默认情况下,代理类在 HTTP 之上使用 SOAP 与 XML Web services 进行通信。但是,Wsdl.exe 可以生成使用 HTTP-GET 协议或 HTTP-POST 协议与 XML Web services 进行通信的代理类。若要指定代理类应该使用 HTTP-GET 或 HTTP-POST,请向 Wsdl.exe 工具提供 /protocol 开关,如下表所述。生成 XML Web services 代理类 在命令提示处,使用 Wsdl.exe 创建代理类,(至少)指定到 XML Web services 或服务说明的 URL 或到保存的服务说明的路径。 
    Wsdl /language:language  /protocol:protocol /namespace:myNameSpace /out:filename /username:username /password:password /domain:domain <url or path>注意:之前列出的参数是 Wsdl.exe 工具通常使用的参数。有关 Wsdl.exe 工具的完整语法,请参见 Web 服务描述语言工具 (Wsdl.exe)。 参数 值 
    <url or path> 到服务说明(以 Web 服务描述语言说明 XML Web services 的文件)的 URL 或路径。 
    如果您指定一个文件,则提供包含服务说明的文件。例如:mywebservice.wsdl如果您指定一个 URL,则该 URL 必须引用 .asmx 页或返回服务说明。对于使用 ASP.NET 创建的 XML Web services,您可以通过将 ?WSDL 追加到 XML Web services 的 URL 来返回服务说明。例如:http://www.contoso.com/MyWebService.asmx?WSDL
     
    /language:language 生成代理类使用的语言。可用选项包括 CS、VB 和 JS,分别指 C#、Visual Basic .NET 和 JScript .NET。默认语言是 C#。(可选) 
    /protocol:protocol 用于与 XML Web services 方法进行通信的协议。可用选项包括 SOAP、HTTP-GET 和 HTTP-POST。默认协议是 SOAP。(可选) 
    /namespace:myNameSpace 生成的代理的命名空间。默认值是全局命名空间。(可选) 
    /out:filename 要创建的包含代理类的文件的名称。默认名称基于实现 XML Web services 的类的名称。(可选) 
    /username:username 当连接到要求身份验证的 Web 服务器时所使用的用户名。(可选) 
    /password:password 当连接到要求身份验证的 Web 服务器时所使用的密码。(可选) 
    /domain:domain 当连接到要求身份验证的 Web 服务器时所使用的域。(可选) 生成的代理类详细信息
    当 Wsdl.exe 用于生成代理类时,将以指定的语言生成一个源文件。该文件包含公开 XML Web services 每个 XML Web services 方法的同步和异步方法的代理类。例如,如果一个 XML Web services 包含一个名为 Add 的 XML Web services 方法,则代理类具有以下方法用来调用 Add XML Web services 方法:Add、BeginAdd 和 EndAdd。代理类的 Add 方法用于与 Add XML Web services 方法进行同步通信,但 BeginAdd 和 EndAdd 方法用于和 XML Web services 方法进行异步通信。有关与 XML Web services 方法异步通信的更多信息,请参见与 XML Web services 进行异步通信。生成的代理类的每个方法都包含适当的代码与 XML Web services 方法进行通信。如果在 XML Web services 和代理类通信过程中出现错误,则将引发一个异常。有关处理异常的详细信息,请参见在 XML Web services 中处理和引发异常。在 XML Web services 方法和关联的代理类方法中的定义顺序之间,参数顺序可能有所不同。在多数情况下,参数顺序相同。但是,如果 XML Web services 需要 Document 格式的 SOAP 消息,则将出现一种参数顺序不相同的情况。如果 XML Web services 方法在定义输入参数之前定义了输出参数,则在代理类中输出参数放置在所有输入参数之后。例如,在下面的代码示例中,XML Web services 方法 MyWebMethod 在声明 inStr 输入参数之前声明了 outStr 输出参数。但是,在代理类中,在声明 outStr 之前先声明 inStr 参数。在某些情况下,由 WSDL.exe 生成的代理类会使用一种不常见的命名方法,将对象强制转换成服务说明中指定的类型。因此,代理类中的生成类型可能不是开发人员想要或预期的类型。例如,当 WSDL.exe 在服务说明中遇到 ArrayList 类型时,它将在生成的代理类中创建一个“对象数组”。若要确保对象类型转换正确,请打开包含生成的代理类的文件,将所有不正确的对象类型更改成所需的对象类型。[Visual Basic]
    ' Declare MyWebMethod in the XML Web service.
    MyWebMethod(ByRef outStr As String, inStr As String)' This is the corresponding MyWebMethod in the proxy class.
    MyWebMethod(inStr As String, ByRef outStr As String)[C#]
    // Declare MyWebMethod in the XML Web service.
    MyWebMethod(out string outStr, string inStr)// This is the corresponding MyWebMethod in the proxy class.
    MyWebMethod(string inStr, out string outStr).在某些情况下,由 WSDL.exe 生成的代理类会使用一种不常见的命名方法,将对象强制转换成服务说明中指定的类型。因此,代理类中的生成类型可能不是开发人员想要或预期的类型。例如,当 WSDL.exe 在服务说明中遇到 ArrayList 类型时,它将在生成的代理类中创建一个 Object 数组。若要确保对象类型转换正确,请打开包含生成的代理类的文件,将所有不正确的对象类型更改成所需的对象类型。