2009-02-27 32 views
1

我有一些UI應用程序存在於用C#編寫的用戶任務欄中。該工具的EXE將被簽入到我們的源代碼管理系統的許多使用它的項目中,以便我們能夠通過檢查更新的EXE來更新它們運行的​​版本。如何從C#中的內存啓動程序?

問題是,當用戶得到exe的最新版本時,程序經常運行,並且他們的機器上的同步失敗。我想修復它,以便程序在運行時不會鎖定exe和任何依賴的DLL,因此可以在不關閉程序的情況下進行同步。

目前,我有一個程序,將可執行文件作爲參數,並通過提前將內容讀取到內存中從內存中啓動它。不幸的是,當涉及程序需要的DLL時,這完全失敗了。

我的代碼現在看起來是這樣的:

public class ExecuteFromMemory 
{ 
    public static void Main(string[] args) 
    { 
     //Figure out the name of the EXE to launch and the arguments to forward to it 
     string fileName = args[0]; 
     string[] realArgs = new string[args.Length - 1]; 
     Array.Copy(args, 1, realArgs, 0, args.Length - 1); 

     //Read the assembly from the disk 
     byte[] binary = File.ReadAllBytes(fileName); 

     //Execute the loaded assembly using reflection 
     Assembly memoryAssembly = null; 
     try 
     { 
      memoryAssembly = Assembly.Load(binary); 
     } 
     catch (Exception ex) 
     { 
      //Print error message and exit 
     } 

     MethodInfo method = memoryAssembly.EntryPoint; 
     if (method != null && method.IsStatic) 
     { 
      try 
      { 
       method.Invoke(null, new object[] { realArgs }); 
      } 
      catch(Exception ex) 
      { 
       //Print error message and exit 
      } 
     } 
     else 
     { 
      //Print error message and exit 
     } 
    } 
} 

我的問題是,我在做什麼那麼傻?有沒有更好的方法來處理這個問題?如果不是,我應該怎麼做來支持處理外部依賴?

例如,如果您嘗試運行使用'Bar.dll'中的函數的'Foo.exe',則上面的代碼無法加載任何相關文件,'Foo.exe'將是可覆蓋的,但是'Bar'。 DLL'仍然被鎖定,不能被覆蓋。

我試圖從GetReferencedAssemblies()方法上加載assmebly,但似乎沒有給出任何跡象應該從哪裏加載程序集的引用程序集列表...我需要搜索對他們自己?如果是這樣,那麼做到這一點的最好方法是什麼?

看起來其他人可能以前碰到過這個,我不想重新發明輪子。

- 更新: EXE已簽入,因爲這是我們如何將內部工具分發給使用它們的團隊的工具。它不適合這種用例,但我沒有機會改變這種策略。

+0

你爲什麼要從內存中執行?這是讓你的程序看起來活病毒的好方法。 – Migol 2009-02-27 16:45:51

回答

1

程序是否需要在更新時保持運行?

通常要更新正在運行的程序,您需要將任何要替換的文件複製到臨時文件夾。然後關閉舊實例,刪除它並將新文件移到正確的位置,然後重新啓動它。

由於最長的部分通常是複製,並且如果臨時文件夾位於同一邏輯驅動器上,文件移動速度非常快,因此可以減少應用程序的停機時間。

4

聲明:我不使用Windows,儘管我熟悉它鎖定事物的奇怪方式。

爲了在運行時更新應用程序,您可能需要有兩個進程:可執行文件本身以及將完成更新過程的更新「助手」應用程序。假設您的應用程序是ProcessA.exe,並且您的更新助手是Updater.exe。您的主程序將下載可執行文件的新副本,並以隨機名稱保存。然後運行更新程序,它監視當前進程的終止情況。當進程終止時,它會顯示一個快速窗口,顯示更新的狀態,將新的可執行文件移動到舊的可執行文件的位置,然後重新啓動該程序。

能夠模擬POSIX文件系統語義並能夠刪除當前正在運行的進程磁盤映像並將其替換爲新文件會更優雅,但我不知道是否可以視窗。在一個POSIX系統上,你可以刪除一個正在使用的文件,直到剩下的文件句柄關閉,它纔會真正被刪除,儘管你可以重用這個文件名。

您可能想看看CodeProject的文章talks about this。它也有一個follow-up article

祝你好運!

0

雖然Michael的回答是這樣做的一種方法,但有些工具明確用於管理桌面上安裝的內容。

你正在做什麼與檢查到源代碼管理的exe是不正常的。如果您有Windows域控制器,則可以使用組策略將程序推送到客戶端。或者,您可以使用Altiris來處理它。

如果你必須繼續你的方式,那麼你有兩種選擇。其一,使用助手/加載器應用程序,在啓動時進行版本檢查。這與firefox的工作方式類似。

第二種方法是構建一個輔助服務,它位於內存中並經常進行輪詢以獲取更新。這就是Google Chrome,Adobe等的工作原理。

相關問題