關於自動更新,在.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()方法就可以使 用了。