解析大型.NET ERP系統 自動更新


C/S架構的應用程序需要支持自動更新功能,當新版本程序發布后,正在運行的客戶端能檢測到新版本的程序,通知用戶是否下載更新。工作以來參與過幾個自動更新模塊的設計與維護,撰文總結自動更新模塊設計與實現。

自動更新組件主要內容

1  版本比較。舊版本如何檢測到新版本,版本信息是程序集自描述的,還是用單獨的文件保存。.NET程序集是自描述的,程序集包含以下幾種版本信息,每個Assebmly包含三個Version
AssemblyFileVersion : 存儲在Win32資源中, CLR不關心這個版本號。
AssemblyInformationnalVersion :存儲在Win32資源中, CLR不關心這個版本號。
AssemblyVersion: 存儲在AssemblyDef manifest metadata table中,CLR會使用這個版本號。

標准版本號物理形式表示為用句點隔開的四段數字,如下面的代碼示例所示。
<major version>.<minor version>.<build number>.<revision>
實際使用中,我們一般只用到前面三段。即
<major version>.<minor version>.<build number>

版本比較舉例:

舊版本 2.4.1.2

新版本 2.4.1.3 或 2.4.2.2 或2.5.1.2。

2 程序下載。采用何種方式,從哪里下載最新版本的程序。

1) Http 協議。從IIS或Tomcat 等Web服務器中下載新版本的程序文件。

2) Ftp協議。從Ftp服務器下載新版本的程序文件。

3) 局域網共享。從內部局域網下載新版本的程序文件。

下載過程中應該支持斷點續傳,支持以壓縮文件的方式傳輸,下載完成后自動解壓縮,執行更新。還可以參考Windows的BITS更新服務,BITS (后台智能傳送服務) 是一個 Windows 組件,它可以在前台或后台異步傳輸文件,為保證其他網絡應用程序獲得響應而調整傳輸速度,並在重新啟動計算機或重新建立網絡連接之后自動恢復文件傳輸。

為了達到傳輸過程中速度最優化,可以考慮調用第三方下載API,實現穿越局域網時,下載速度最快。

4) ClickOnce方式。將程序部署在IIS網站中,配置ClickOnce,參考文章 ClickOnce部署

 

3 執行更新。如果更新程序是壓縮格式的zip/rar格式文件,可解壓縮后復制到應用程序目錄即可。如果更新程序是安裝格式的Installer文件,則需要先退出當前程序,啟動安裝程序包。

當前程序正在執行時,將更新程序覆蓋過來,會遇到文件被進程占用的情況,有以下三種解決方案:

1) 根據更新程序生成一個批處理命令,主要內容是將更新程序中的文件復制到當前程序所在文件夾。命令主要包含以下三個部分,退出當前程序,執行文件復制,啟動應用程序。

2) 應用程序啟動一個獨立的更新程序Update.EXE,由更新程序完成文件的復制和程序的啟動。

3) 調用Volume Shadow Copy Service,這個服務支持當文件正在被進程使用,仍可以復制。

詳細參考以下網站信息 Volume Shadow Copy Service

 

文件的存儲方式

1) 文件包含版本信息,舉例EnterpriseSolution-5.3.0.0-20150401.zip,表示是5.3版本的,構建日期是2015年4月1日。在檢測更新文件時,需要遍歷同版本或是高版本的文件,取最新的那個文件。

2) 文件不包含版本信息,需要用獨立的描述文件表達版本信息。比如

<?xml version="1.0" encoding="utf-8" ?>
<Content>
  <Project id="Enterprise.Sales.dll" Edition="1.2"> </Project>
  <Project id="Enterprise.Purchasing.dll" Edition="1.2"> </Project>
  <Project id="Enterprise.Inventory.dll" Edition="1.3"> </Project>
  <Project id="Enterprise.GeneralLedger.dll" Edition="1.5"> </Project>
</Content>

通過這個描述文件,找到最新版本的文件,分批下載回來。對於服務器中存在多個版本的文件情況,可用文件夾(1.2,1.5)的方式將各版本的程序文件放在各自的目錄中,通過上面的版本描述文件分別在各自的版本目錄中尋找文件。

 

版本檢測

檢測版本,發現新版本后啟動更新程序Update.EXE,退出當前程序。

string clientVersion = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductVersion;
string serverVersion = FileVersionInfo.GetVersionInfo("Main.exe", server)).ProductVersion;

if (new Version(serverVersion).CompareTo(new Version(clientVersion)) > 0)
{
        var process = new Process
        {
                 StartInfo = new ProcessStartInfo
                 {
                      FileName = "Update.exe",
                      Arguments = "LOCAL"
                  }
        };
        process.Start();
        Environment.Exit(0);
}
 
 

外殼程序

啟動外殼程序,在局域網(工作組)中常用來解決權限問題。

private static void Shell(string arguments)
{
        Process process = new Process();
        ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe", arguments);
        processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo = processStartInfo;
        process.Start();
}
 

常用在net use命令,舉例如下:

net use ipipc$ " " /user:" " 建立IPC空鏈接

net use ipipc$ "密碼" /user:"用戶名" 建立IPC非空鏈接

net use h: ipc$ "密碼" /user:"用戶名" 直接登陸后映射對方C:到本地為H:

net use h: ipc$ 登陸后映射對方C:到本地為H:

 

網絡連接檢查

當准備檢測更新時,我需要檢測網絡是否通暢,需要用下面的方法:

1) 局域網模式下,用SystemInformation.Network可達到目的。

2) 要從外網下載程序,需要檢查外網是否連通,可以采用PING一個IP地址的方式,要求這個IP地址或是域名非常穩定。

可以調用C#的Ping類型完成目的,參考代碼:

Ping ping = new Ping();
PingOptions poptions = new PingOptions();
poptions.DontFragment = true;

也可以調用COM接口InternetGetConnectedState,用於檢測網絡連接狀態。

[DllImport("wininet")]
private extern static bool InternetGetConnectedState(out int connectionDescription, int reservedValue);

參考說明 InternetGetConnectedState function

stackoverflow中有一篇講解判斷網絡連接的問答,地址是http://stackoverflow.com/questions/13457407/why-is-getisnetworkavailable-always-returning-true

要檢測廣域網是否連接,需要使用InternetGetConnectedState()或WinINet API。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM