黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

java WebService + C# winform實現(xiàn)軟件更新功能

系統(tǒng) 2244 0

??? 由于項目的需求的變動,客戶想要把原來由 javaEE 開發(fā)的 B/S 架構(gòu)一個系統(tǒng)平臺換為 C/S 架構(gòu)的,考慮到項目進度和效率的問題,項目組決定采用 C# winform 來實現(xiàn)客戶端的開發(fā),而服務(wù)器端直接引用原有的系統(tǒng)業(yè)務(wù)。考慮到客戶端軟件可能以后會不斷地需要更新,因此做了一個軟件自動更新的功能。閑話少說,轉(zhuǎn)到正題!

首先我先要介紹一下該功能的總體實現(xiàn)思路:

首先考慮的是在服務(wù)端要有哪些方法來實現(xiàn)軟件的更新功能呢?

一、軟件需要更新,必然涉及到文件的讀取操作,因此我們要有一個讀取文件的方法;

二、軟件更新的過程中需要用進度條來展示更新的進度,因此我們服務(wù)端還需要有一個獲取文件大小的方法;

三、這是最重要的一點,就是客戶端該如何來確認是否需要更新,更新那些文件?因此我們需要用一個 xml 文件來描述這些信息。

其次要考慮一下客戶端的實現(xiàn)方式了,客戶端應(yīng)該如何實現(xiàn)呢?

一、 客戶端首先要判斷軟件是否需要更新,要更新那些文件,因此我們必須先要把服務(wù)器上對軟件更新的 xml 描述文件先從服務(wù)端下載下來,然后與客戶端上的 xml 文件進行比較,看是否需要更新;

二、 若通過 xml 文件比較后,發(fā)現(xiàn)需要更新后,讀取 xml 文件中需要更新的文件列表,然后依次下載需要更新的文件到臨時的更新文件夾;

三、 停止主程序進程,替換掉程序中原有的文件,最后關(guān)閉更新程序,啟動主程序,更新完成!

?

實現(xiàn)程序更新的效果圖:

?


java WebService + C# winform實現(xiàn)軟件更新功能
?

?

現(xiàn)在我們就根據(jù)我們的總體實現(xiàn)思路來一步一步完成該應(yīng)用的實現(xiàn):

一、 WebService 的開發(fā)源碼
根據(jù)上面的思路我們分析出實現(xiàn)該應(yīng)用我們至少需要兩個方法,一個是讀取文件的方法,一個是獲取文件大小的方法,本人采用的是 JAX-WS 2.1 來實現(xiàn) WebService 的,采用其他的服務(wù)類庫也可以,只要實現(xiàn)該服務(wù)就可以了,我的服務(wù)實現(xiàn)類如下:

?

    package com.updatesoft.service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;

/**
 * 更新軟件操作類
 * @author jin
 *
 */
public class UpdateSoft {

	/**
	 * 獲取文件大小
	 * @param fileName 文件名稱
	 * @return 文件大小(字節(jié))
	 */
	public long getFileSize(String fileName) {
		int nFileLength = -1;   
		try {
			
			String str = URLDecoder.decode(getClass().getClassLoader().getResource("com").toString(),"UTF-8");
			str= str.substring(0, str.indexOf("WEB-INF/classes")); 
			str=str.substring(6);
			System.out.println("路徑:" + str);
			
			File file = new File(str + fileName);
			if (file.exists()) {
				FileInputStream fis = null;
				fis = new FileInputStream(file);
			    nFileLength = fis.available();
			} else {
				System.out.println("文件不存在");
			}

		}catch (IOException e) {   
			e.printStackTrace();   
		}catch (Exception e) {   
			e.printStackTrace();   
		}   
		System.out.println(nFileLength);
		return nFileLength;
	}

	/**
	 * 根據(jù)偏移量和字節(jié)緩存大小分段獲取文件字節(jié)數(shù)組
	 * @param fileName 文件名稱
	 * @param offset 字節(jié)偏移量
	 * @param bufferSize 字節(jié)緩存大小
	 * @return 文件字節(jié)數(shù)組
	 */
	public byte[] getUpdateFile(String fileName, int offset, int bufferSize) {
		byte[] ret = null;   
		try { 
			String str = URLDecoder.decode(getClass().getClassLoader().getResource("com").toString(),"UTF-8");
			str= str.substring(0, str.indexOf("WEB-INF/classes")); 
			str=str.substring(6);
			File file = new File(str + fileName);
			
		    if (!file.exists()) {   
		        return null;   
		    }   
		    FileInputStream in = new FileInputStream(file);   
		    ByteArrayOutputStream out = new ByteArrayOutputStream(1024);   
		    byte[] b = new byte[1024];   
		    int n;
		    int t = 0;
		    while ((n = in.read(b)) != -1) { 
		    	if(t >= offset && t< offset + bufferSize){
		    		out.write(b, 0, n);
		    	}
		    	t += n;
		    }   
		    in.close();   
		    out.close();   
		    ret = out.toByteArray();
		} catch (IOException e) {   
		    e.printStackTrace();   
		}   
		return ret;
	}
}
  

?

客戶端所需要調(diào)用的服務(wù)方法我們已經(jīng)實現(xiàn)了,接下來我們需要準(zhǔn)備我們軟件更新的資源了(即需要更新的文件和更新文件的描述文件 update.xml )。資源文件根據(jù)需求上傳到服務(wù)器中,其中 update.xml 文件格式如下:

    <?xml version="1.0" encoding="UTF-8"?>
<update>  
    <forceUpdate>false</forceUpdate>  
    <version>20100812</version>  
    <subversion>1</subversion>  
    <filelist count="5">  
        <file name="music/陳瑞 - 白狐.mp3">true</file>
        <file name="music/韓紅 - 擦肩而過.mp3">true</file> 
		<file name="music/林俊杰 - 背對背擁抱.mp3">true</file>
        <file name="music/油菜花-成龍.mp3">true</file>
		<file name="music/鄭智化 - 別哭我最愛的人.mp3">true</file>
    </filelist>  
    <executeFile>SystemUpdateClient.exe</executeFile>  
</update>
  

?

根節(jié)點為 update forceUpdate 為是否強制更新, ture 則為是, false 則為否; version 為主版本號, subversion 為次版本號, flielist 為需要更新的文件列表,屬性 count 指定需要更新的文件數(shù), flie 為文件節(jié)點, name 屬性指定文件名稱,值 true 為需要更新,值 false 為不需要更新。 executeFile 指定軟件更新完成后需要重新啟動的可執(zhí)行文件。

?

二、 客戶端的開發(fā)源碼

客戶端的實現(xiàn)也比較簡單,本人采用的是 vs2008 的開發(fā)工具,在解決方案中新建一個軟件更新的窗體,在窗體中拖入一個文本框和兩個進度條,文本框用于顯示更新過程,兩個進度條一個用于顯示總進度,一個顯示單個文件進度。為了 解決多線程環(huán)境中跨線程改寫 ui 控件屬性問題,我這里采用了代理方法,實現(xiàn)代碼如下:

?

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Xml;

namespace SystemUpdateClient
{
    public partial class update : Form
    {
        /// <summary>   
        /// 每次下載并寫入磁盤的文件數(shù)據(jù)大小(字節(jié))   
        /// </summary>   
        private static int BUFFER_SIZE = 15 * 1024;   
  
        //把窗體改為單例模型   
        private static update updateForm;   
        public static update getUpdateForm()   
        {   
            if (updateForm == null)   
            {   
                updateForm = new update();   
            }   
            return updateForm;   
        }   
        //構(gòu)造函數(shù)改為私有,外部程序不可以使用 new() 來創(chuàng)建新窗體,保證了窗體唯一性   
        private update()   
        {      
            InitializeComponent();   
        }

        //******** 定義代理方法,解決多線程環(huán)境中跨線程改寫 ui 控件屬性,開始 ********

        //定義設(shè)置一個文本的委托方法(字符串)
        private delegate void setText(string log);
        //定義設(shè)置一個進度的委托方法(整型)
        private delegate void setProcess(int count);

        //設(shè)置總進度條的最大數(shù)
        private void setProgressBar1_Maximum(int count)
        {
            progressBar1.Maximum = count;
        }
        //設(shè)置單文件進度條的最大數(shù)
        private void setProgressBar2_Maximum(int count)
        {
            progressBar2.Maximum = count;
        }
        //設(shè)置總進度條的當(dāng)前值
        private void setProgressBar1_value(int count)
        {
            progressBar1.Value = count;
        }
        //設(shè)置單文件進度條當(dāng)前值
        private void setProgressBar2_value(int count)
        {
            progressBar2.Value = count;
        }
        //設(shè)置總文件進度條步進進度
        private void addProgressBar1_value(int count)
        {
            if (progressBar1.Maximum > progressBar1.Value)
            {
                progressBar1.Value += count;
            }
            else
            {
                progressBar1.Value = progressBar1.Maximum;
            }
        }
        //設(shè)置單文件進度條步進進度
        private void addProgressBar2_value(int count)
        {
            if (progressBar2.Maximum > progressBar2.Value)
            {
                progressBar2.Value += count;
            }
            else
            {
                progressBar2.Value = progressBar2.Maximum;
            }
        }
        //設(shè)置文本框的值
        private void UpdateText(string log)
        {
            textBox1.Text += log;
        }

        //******** 定義代理方法,解決多線程環(huán)境中跨線程改寫 ui 控件屬性  結(jié)束 ********

        /// <summary>
        /// 窗體顯示時,調(diào)用 invokeThread 方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void update_Shown(object sender, EventArgs e)
        {
            invokeThread();
        }

        /// <summary>
        /// 開啟一個線程,執(zhí)行 update_function 方法
        /// </summary>
        void invokeThread()
        {
            Thread th = new Thread(new ThreadStart(update_function));
            th.Start();
        }

        /// <summary>
        /// 自動更新方法,整合實現(xiàn)下面的業(yè)務(wù)邏輯。
        /// </summary>
        private void update_function()
        {
            //判斷 位于本地客戶端程序文件夾 update 是否存在
            if (Directory.Exists(Application.StartupPath + "/update"))
            {
                //存在則刪除,true 表示移除包含的子目錄及文件
                Directory.Delete("update/", true);
            }
            try{
                //通過 webservice 從服務(wù)器端獲取更新腳本文件 update.xml
                getUpdateXMLFile();
            }
            catch (Exception e)
            {
                MessageBox.Show("無法進行更新,訪問服務(wù)器失敗!\n\r原因:" + e.Message, "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            //判斷強制更新開關(guān)
            if (isForceUpdate())
            {
                //通過 webservice 從服務(wù)器端下載更新程序文件
                downloadFiles();
            }
            else
            {
                //比較版本號
                if (verifyVersion())
                {
                    //通過 webservice 從服務(wù)器端下載更新程序文件
                    downloadFiles();
                }
            }
            DialogResult result = MessageBox.Show("更新完成!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            if (result == DialogResult.OK)
            {
                //啟動客戶端主程序,退出更新程序
                appExit();
            }
        }

        /// <summary>
        /// 下載 update.xml
        /// </summary>
        private void getUpdateXMLFile()
        {
            //執(zhí)行委托方法,更新文本控件內(nèi)容
            textBox1.Invoke(new setText(this.UpdateText), new object[] { "正在從服務(wù)器下載 更新腳本文件 update.xml \r\n" });
            
            //創(chuàng)建一個文件傳送的 webservice 接口實例
            updateservice.UpdateSoftDelegateClient sendFileWS = new updateservice.UpdateSoftDelegateClient();
       
            //通過 webservice接口 獲取服務(wù)器上 update.xml 文件的長度。
            long fileSize = sendFileWS.getFileSize("update.xml");
            //判斷本地客戶端文件夾下 update 目錄是否存在
            if (!Directory.Exists(Application.StartupPath + "/update"))
            {
                //不存在則創(chuàng)建 update 目錄
                Directory.CreateDirectory(Application.StartupPath + "/update");
            }
            //通過定義文件緩沖區(qū)分塊下載 update.xml 文件
            for (int offset = 0; offset < fileSize; offset += BUFFER_SIZE)
            {
                //從服務(wù)器讀取指定偏移值和指定長度的二進制文件字符數(shù)組
                byte[] bytes = sendFileWS.getUpdateFile("update.xml", offset, BUFFER_SIZE);
                //如果 字符數(shù)組不為空
                if (bytes != null)
                {
                    //以追加方式打開 update.xml 文件 
                    using (FileStream fs = new FileStream(Application.StartupPath + "/update/update.xml", FileMode.Append))
                    {
                        //寫入數(shù)據(jù)
                        fs.Write(bytes, 0, bytes.Length);
                        fs.Close();
                    }
                }
            }
           

        }

        /// <summary>
        /// 是否開啟強制更新。
        /// </summary>
        /// <returns>true 開啟強制更新,false 比較版本號后再更新</returns>
        private bool isForceUpdate()
        {
            try
            {
                //開始解析 update/update.xml 新文件
                XmlDocument doc = new XmlDocument();
                doc.Load("update/update.xml");
                XmlElement root = doc.DocumentElement;
                //節(jié)點是否存在
                if (root.SelectSingleNode("forceUpdate") != null)
                {
                    //獲取 forceUpdate 節(jié)點的內(nèi)容
                    string forceUpdate = root.SelectSingleNode("forceUpdate").InnerText;
                    doc = null;
                    if (forceUpdate.Equals("true"))
                    {
                        textBox1.Invoke(new setText(this.UpdateText), new object[] { "強制更新開關(guān)已打開,不再匹配版本號。 \r\n" });
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    doc = null;
                    return false;
                }


            }
            catch
            {
                //發(fā)生異常,則更新程序,覆蓋 update.xml
                MessageBox.Show("版本文件解析異常,服務(wù)器端 update.xml 可能已經(jīng)損壞,請聯(lián)系管理員。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return true;
            }
        }


        /// <summary>
        ///  解析 update.xml 文件,比較version 和 subversion 判斷是否有新版本
        /// </summary>
        /// <returns>true 有新版本,false 版本相同</returns>
        private bool verifyVersion()
        {
            try
            {
                if (!File.Exists("update.xml"))
                {
                    return true;
                }
                //開始解析 update.xml 舊文件
                XmlDocument doc1 = new XmlDocument();
                doc1.Load("update.xml");
                XmlElement root1 = doc1.DocumentElement;

                //開始解析 update/update.xml 新文件
                XmlDocument doc2 = new XmlDocument();
                doc2.Load("update/update.xml");
                XmlElement root2 = doc2.DocumentElement;

                if (root1.SelectSingleNode("version") != null && root1.SelectSingleNode("subversion") != null && root2.SelectSingleNode("version") != null && root2.SelectSingleNode("subversion") != null)
                {
                    int old_version = Convert.ToInt32(root1.SelectSingleNode("version").InnerText);
                    int old_subversion = Convert.ToInt32(root1.SelectSingleNode("subversion").InnerText);
                    int new_version = Convert.ToInt32(root2.SelectSingleNode("version").InnerText);
                    int new_subversion = Convert.ToInt32(root2.SelectSingleNode("subversion").InnerText);

                    doc1 = null;
                    doc2 = null;

                    textBox1.Invoke(new setText(this.UpdateText), new object[] { "正在判斷版本號...\r\n" });
                    //判斷版本號和子版本號
                    if (old_version == new_version && old_subversion == new_subversion)
                    {
                        textBox1.Invoke(new setText(this.UpdateText), new object[] { "已經(jīng)是最新版本,無需更新\r\n" });
                        return false;
                    }
                    else
                    {
                        textBox1.Invoke(new setText(this.UpdateText), new object[] { "發(fā)現(xiàn)新版本,開始讀取更新列表 \r\n" });
                        return true;
                    }
                }
                else
                {
                    textBox1.Invoke(new setText(this.UpdateText), new object[] { "無法解析版本號,將下載更新全部文件...\r\n" });
                    doc1 = null;
                    doc2 = null;
                    return true;
                }
            }
            catch
            {
                //發(fā)生異常,則更新程序,覆蓋 update.xml
                MessageBox.Show("版本文件解析異常,服務(wù)器端 update.xml 可能已經(jīng)損壞,請聯(lián)系管理員。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                
                return true;
            }
        }

        /// <summary>
        /// 解析 update.xml,下載更新文件
        /// </summary>
        public void downloadFiles()
        {
            //解析 update.xml
            XmlDocument doc = new XmlDocument();
            doc.Load("update/update.xml");
            XmlElement root = doc.DocumentElement;
            XmlNode fileListNode = root.SelectSingleNode("filelist");
            //獲取更新文件的數(shù)量
            int fileCount = Convert.ToInt32(fileListNode.Attributes["count"].Value);
            //調(diào)用委托方法,更新控件內(nèi)容。
            textBox1.Invoke(new setText(this.UpdateText), new object[] { "需更新文件數(shù)量 " + fileCount.ToString() + "\r\n" });
            
            //結(jié)束 SystemUpdateClient.exe 進程
            System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();
            foreach (System.Diagnostics.Process process in processes)
            {
                if (process.ProcessName == "SystemUpdateClient.exe")
                {
                    process.Close();
                    break;
                }
            }

            //總文件大小,用于設(shè)置總進度條最大值
            long totalFileSize = 0;

            //循環(huán)文件列表,獲取總文件的大小
            for (int i = 0; i < fileCount; i++)
            {
                XmlNode itemNode = fileListNode.ChildNodes[i];
                //獲取更新文件名
                string fileName = itemNode.Attributes["name"].Value;
                //獲取需要更新文件的總大小,調(diào)用 webservice 接口
                updateservice.UpdateSoftDelegateClient sendFileWS = new updateservice.UpdateSoftDelegateClient();
                //獲取文件長度(字節(jié))
                long fileSize = sendFileWS.getFileSize(fileName);
                totalFileSize += fileSize;
            }

            //調(diào)用委托方法,設(shè)置總進度條的最大值。
            progressBar1.Invoke(new setProcess(this.setProgressBar1_Maximum), new object[] { (int)(totalFileSize / BUFFER_SIZE) + 1 });
            //調(diào)用委托方法,更新控件內(nèi)容。
            textBox1.Invoke(new setText(this.UpdateText), new object[] { "開始更新...\r\n" });

            //循環(huán)文件列表
            for (int i = 0; i < fileCount; i++)
            {
                XmlNode itemNode = fileListNode.ChildNodes[i];
                //獲取更新文件名
                string fileName = itemNode.Attributes["name"].Value;
                //調(diào)用委托方法,更新控件內(nèi)容。
                textBox1.Invoke(new setText(this.UpdateText), new object[] { "正在下載文件 " + fileName + "\r\n" });
                //分塊下載文件,調(diào)用 webservice 接口
                updateservice.UpdateSoftDelegateClient sendFileWS = new updateservice.UpdateSoftDelegateClient();
                //獲取文件長度(字節(jié))
                long fileSize = sendFileWS.getFileSize(fileName);
                //調(diào)用委托方法,更新進度條控件內(nèi)容。
                progressBar2.Invoke(new setProcess(this.setProgressBar2_Maximum), new object[] { (int)(fileSize / BUFFER_SIZE) + 1 });
                progressBar2.Invoke(new setProcess(this.setProgressBar2_value), new object[] { 0 });
                //通過 webservice 接口 循環(huán)讀取文件數(shù)據(jù)塊,每次向前步進 BUFFER_SIZE
                for (int offset = 0; offset < fileSize; offset += BUFFER_SIZE)
                {
                    Byte[] bytes = sendFileWS.getUpdateFile(fileName, offset, BUFFER_SIZE);
                    if (bytes != null)
                    {
                        
                        if (fileName.LastIndexOf("/") != 0)
                        {
                            string newpath = fileName.Substring(0, fileName.LastIndexOf("/"));
                            if (!Directory.Exists(Application.StartupPath + "/update/" + newpath))
                            {
                                //不存在則創(chuàng)建 update 目錄
                                Directory.CreateDirectory(Application.StartupPath + "/update/" + newpath);
                            }
                        }
                        //將下載的更新文件寫入程序目錄的 update 文件夾下
                        using (FileStream fs = new FileStream(Application.StartupPath + "/update/" + fileName, FileMode.Append))
                        {
                            fs.Write(bytes, 0, bytes.Length);
                            fs.Close();
                        }
                    }
                    bytes = null;
                    progressBar2.Invoke(new setProcess(this.addProgressBar2_value), new object[] { 1 });
                    progressBar1.Invoke(new setProcess(this.addProgressBar1_value), new object[] { 1 });
                }
                //替換文件
                try
                {
                    if (fileName.LastIndexOf("/") != 0)
                    {
                        string newpath = fileName.Substring(0, fileName.LastIndexOf("/"));
                        if (!Directory.Exists(Application.StartupPath + "/" + newpath))
                        {
                            //不存在則創(chuàng)建 update 目錄
                            Directory.CreateDirectory(Application.StartupPath + "/" + newpath);
                        }
                    }
                    if (fileName != "SystemUpdateClient.XmlSerializers.dll" || fileName != "SystemUpdateClient.exe.config" || fileName != "SystemUpdateClient.pdb" || fileName != "SystemUpdateClient.exe")
                    {
                        File.Copy("update/" + fileName, fileName, true);
                    }
                }
                catch
                {
                    textBox1.Invoke(new setText(this.UpdateText), new object[] { "無法復(fù)制" + fileName + "\r\n" });
                }
                //progressBar1.Invoke(new setProcess(this.addProgressBar1_value), new object[] { 1 });
            }

            textBox1.Invoke(new setText(this.UpdateText), new object[] { "更新完成,更新程序正在做最后操作\r\n" });

            //最后復(fù)制更新信息文件
            File.Copy("update/update.xml", "update.xml", true);

        }

        /// <summary>
        /// 啟動客戶端主程序,退出更新程序
        /// </summary>
        private void appExit()
        {
            //判斷 位于本地客戶端程序文件夾 update 是否存在
            if (Directory.Exists(Application.StartupPath + "/update"))
            {
                //存在則刪除,true 表示移除包含的子目錄及文件
                Directory.Delete("update/", true);
            }

            //獲取主程序執(zhí)行文件名
            XmlDocument doc = new XmlDocument();
            doc.Load("update.xml");
            XmlElement root = doc.DocumentElement;
            string executeFile = string.Empty;
            //節(jié)點是否存在
            if (root.SelectSingleNode("executeFile") != null)
            {
                //獲取 executeFile 節(jié)點的內(nèi)容
                executeFile = root.SelectSingleNode("executeFile").InnerText;
            }
            doc = null;
            //啟動客戶端程序
            System.Diagnostics.Process.Start(Application.StartupPath + @"\" + executeFile);
            //更新程序退出
            Application.Exit();
        }
       
    }
}

  

?

通過源代碼大家可以通過方法 update_function() 看出該應(yīng)用的流程來,它首先是從服務(wù)端下載 update.xml 文件 ( 調(diào)用 getUpdateXMLFile()) ,根據(jù)下載的 xml 文件判斷是否需要強制更新(調(diào)用 isForceUpdate() ),若是需要強制更新,那么將會強制更新所有的文件(調(diào)用 downloadFiles() ),若不需要強制更新則比較版本號(調(diào)用 verifyVersion() ),若版本號不同,則更新客戶端軟件,執(zhí)行更新操作(調(diào)用 downloadFiles() ),更新完成后退出更新程序,啟動主程序的可執(zhí)行文件(調(diào)用 appExit() )。

到此我們整個軟件更新應(yīng)用算是已經(jīng)完成了,關(guān)于代碼的具體含義,方法的執(zhí)行內(nèi)容,大家看一下代碼就明白了,很好理解的! ?

java WebService + C# winform實現(xiàn)軟件更新功能


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論