程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#利用批處理實現正在運行的程序自動更新

C#利用批處理實現正在運行的程序自動更新

編輯:關於C#

關於自動更新,在.NET下面已經是很普通的事情,無非就是在服務器端保存配置好要更新的程序,然後客 戶端再寫一個小程序來檢測,有更新的則復制過來.就這麼個思路,這麼個簡單的問題還要占一篇首頁?但你 可別急,看看我的標題,再慢慢的看下去,或許哪一天,你可能還真的會用得著呢,就算用不著,相信對各位回 頭溫習一下久違的Command也是不錯呀!

利用ShareDevelop的ICSharpCode.Core實現了一個插件應用程序,這兩天想要弄個自動更新,將更新功 能作為插件包括在應用程序中,本來以為按照上面的思路是很容易實現的,也確實實現了部分,為什麼說部 分呢,因為主Exe文件沒有更新成功啦!想想原因其實也很簡單:主Exe本身就在運行,在運行階段的Exe或DLL 是沒法復蓋的.這下子,這可怎麼辦?這時一個想法冒出,先將主Exe進程殺掉,然後再復制不成嗎?咦,好象是 道理哦,自殺了之後,自然可以復制過來呀,但是轉念又想,如果主Exe自己都不存在,那後面的復制功能怎麼 才能執行呢?難不成因為不差錢,有錢能使鬼推磨,幫主Exe一把?

這世界當然是沒有鬼的,即使有,它也不可能這麼厲害的能幫到主Exe的,在座位上腦子裡想的總是自殺 再重生這個方案.Google,Baidu這些大神祭起半天也沒有找到好的解決方案,只好退下來.看來只有靠自己 自力更生,當然這個不一定行得通,但至少嘗試過了……

不就是復制嘛?就是copy呀,百無頭緒當中,我在cmd中(我一般是會開著cmd的), 無意識的敲著 copy/?,xcopy/?之類的查看,其中xcopy的幫助還真是提醒了我,請看下面:(繁體系統,粘貼過來的,所以沒 有轉換成簡體)

XCopyHelp
C:\>xcopy /?
復制檔案和樹狀目錄.

XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
                           [/C] [/I] [/Q] [/F] [/L] [/G] [/H] [/R] [/T] [/U]
                           [/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z] \r\r
                           [/EXCLUDE:file1[+file2][+file3]]

  source       指定要復制的檔案.
  destination  指定位置或者/以及新檔案的名稱.
  /A           只復制設定成保存屬性的檔案,不要改變屬性的設定.
  /M           只復制設定成保存屬性的檔案,並清除保存屬性.
  /D:m-d-y     復制在指定日期當天或之後發生變更的檔案.如果沒有給日期,
               只復制那些來源檔案日期比目的檔案日期為新的檔案.
  /EXCLUDE:file1[+file2][+file3]
               指定檔案清單字串.每個字串
               應該在檔案中的不同行.如果有字串對應到要進行復制的檔案絕
               對路徑的任何部分,這個檔案會被排除復制.例如,指定字串
               \obj\ 或 .obj 的話,會排除所有在 obj 目錄下副檔名是
               .obj 的檔案復制.
  /P           在建立每個目的檔案時顯示提示.
  /S           復制每個目錄及其包含的子目錄,不復制空目錄.
  /E           復制每個目錄及其包含的子目錄,也復制空目錄./S 與 /E
               相同,能夠用來修改 /T.
  /V           驗證每個新檔案.
  /W           在復制之前提示您按鍵繼續.
  /C           如果錯誤發生時也繼續復制.
  /I           如果目的不存在且復制一個以上的檔案的話,就假設指定的
               目的一定是目錄.
  /Q           在復制時不要顯示檔名.
  /F           在復制時顯示來源及目的檔案的全部檔名.
  /L           顯示要復制的檔案.
  /G           允許加密檔案復制到不支援加密的
               目的地.
  /H           時復制隱藏檔和系統檔.
  /R           覆蓋唯讀檔案.
  /T           建立目錄結構,但不復制其中的檔案.不包括空目錄及子目錄.
               /T /E 會包括空目錄及子目錄.
  /U           只復制已經存在目的位置的檔案.
  /K           復制檔案屬性.通常 Xcopy 會重設唯讀的屬性.
  /N           用所產生的短檔名來進行復制.
  /O           復制檔案所有權及 ACL 資訊.
  /X           復制檔案審查設定 (包含 /O).
  /Y           不要提示您確認是否要覆蓋一個已經存在的檔案.
  /-Y          示您確認是否要覆蓋一個已經存在的檔案.
  /Z           在可重新開始的模式中復制網路檔案.

參數 /Y 可以在 COPYCMD 環境變數中預先設定.但可以在命令列中用 /-Y 參數

來覆蓋原有設定.

對哦,xcopy是可以復制更深層次的目錄和文件的,那我如果建一個bat文件,執行的是復制功能,然後再 用一個bat來調用他,並且用一個bat文件去殺掉某一個文件,然後再復制新的,再啟動是沒有什麼問題的吧. 試試:

首先,下載園子裡jenry的那篇自動更新的源碼 (http://www.cnblogs.com/jenry/archive/2006/08/15/477302.html);

因為我覺得他這篇自動更新的文章寫的簡單但實用,再加上有網友在他的基礎上添加了一個aulwriter 工具,所以自動更新直接用這個也蠻方便的.

第二步,我添加了一個方法KillSelfThenRun()用於刪除正在運行的主Exe,然後再重啟新的主Exe。代 碼全部粘貼如下:

KillSelfThenRun
        private void KillSelfThenRun()
        {
            string strXCopyFiles = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "XCopyFiles.bat");
            using (StreamWriter swXcopy = File.CreateText(strXCopyFiles))
            {
                string strOriginalPath = tempUpdatePath.Substring(0, tempUpdatePath.Length - 1);
                swXcopy.WriteLine(string.Format(@"
                                                 @echo off
                                                 xcopy /y/s/e/v " + strOriginalPath + " " + Directory.GetCurrentDirectory() +"", AppDomain.CurrentDomain.FriendlyName));
            }
            string filename = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "killmyself.bat");
            using (StreamWriter bat = File.CreateText(filename))
            {
                // 自刪除,自啟動
                bat.WriteLine(string.Format(@"
                        @echo off
                        :selfkill
                        attrib -a -r -s -h ""{0}""
                        del ""{0}""
                        if exist ""{0}"" goto selfkill
                        call XCopyFiles.bat
                        del XCopyFiles.bat
                        del /f/q " + tempUpdatePath+Environment.NewLine + " rd " + tempUpdatePath +Environment.NewLine + " start " + mainAppExe +Environment.NewLine + " del %0 ", AppDomain.CurrentDomain.FriendlyName));
            }

            // 啟動自刪除批處理文件
            ProcessStartInfo info = new ProcessStartInfo(filename);
            info.WindowStyle = ProcessWindowStyle.Hidden;
            Process.Start(info);

            // 強制關閉當前進程
            Environment.Exit(0);
        }

第三步調用時,原程序本身就有一個Try的做法,就在Catch裡面判斷一下,如果出現IOException,就 調用這個方法。

點擊完成復制更新文件到應用程序目錄

        private void btnFinish_Click(object sender, System.EventArgs e)
        {
            this.Dispose();
            //KillSelfThenRun();
            try
            {
                CopyFile(tempUpdatePath, Directory.GetCurrentDirectory ());
                System.IO.Directory.Delete(tempUpdatePath, true);
            }
            catch (Exception ex)
            {
                if (ex.GetType() == typeof(IOException))
                {
                    KillSelfThenRun();
                }
                else
                {
                    MessageBox.Show(ex.Message.ToString());
                }
            }
            if (true == this.isRun) Process.Start(mainAppExe);
        }

最後測試,在xp下自身更新通過。

大概就是這樣子,源碼各位下載上面jenry的那個組件,然後再上KillSelfThenRun()方法就可以使 用了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved