2010-02-25 29 views
12

我有一個.exe程序集和一組引用的程序集,我希望能夠部署更新的代碼。我不需要實際更改運行代碼,但下次啓動可執行文件時,我希望它能夠獲取更新後的代碼。目前,當我嘗試複製正在運行的文件時,出現有關另一個進程正在使用的.exe文件的錯誤。如何更新正在運行的c#進程(AKA熱部署)的程序集?

總結;如何在.exe正在使用時更新代碼?

+0

似乎有一個Codeplex項目針對.NET的熱部署。我還沒有嘗試,但:http://hotdeploy.codeplex.com/ – 2010-02-25 16:48:49

回答

17

這很容易做到。您可以重命名該文件,Windows對該句柄有一個鎖定,而不是該文件的目錄條目。現在您可以複製更新而沒有問題。剩下要做的就是在應用程序重新啓動後襬脫重命名的文件。如有必要。

+0

你可以提供更多的細節/代碼? – Jerry 2013-04-29 13:23:34

+0

除了答案之外,您可能還要注意,在重命名文件之前,用戶可能需要首先從調試過程中分離,否則IDE(即Visual Studio)將不允許編輯源文件。 – 2014-03-18 18:00:12

+0

這是不好的解決方案,因爲重命名後你將會損壞快捷方式。您應該使用幫助器應用程序。 – l0pan 2017-02-28 22:52:58

3

我不認爲這是可能的。例如,在零宕機時部署asp.net應用程序時,最佳做法是使用負載平衡器,以便取下一個實例,更新它,然後取下另一個實例進行更新。

2

裝配體在使用中時無法更新。這種情況的最佳選擇是製作一個小的可執行文件,它執行程序集的陰影副本,並從新位置啓動它們。

這樣,當用戶啓動程序時,您可以從部署站點複製(本地)複製,該複製始終可以被覆蓋。

1

有關以下內容:

  1. 部署的exe到更新的文件夾。
  2. 每當應用程序啓動,它會 檢查更新文件夾。
  3. 如果它不是空的,執行復制 程序
  4. 的複製程序將隨後更換 與一個在 更新文件夾
  5. 在更新文件夾中刪除任何
  6. 然後重新啓動該exe現有的EXE
1

最好的想法應該是已經提出的其他答案之一...就像使用MEF和/或ClickOnce進行重構一樣。但是,這些解決方案無法幫助您進行「部署」。他們要求您對exe文件進行更改,或者創建引導程序可執行文件,這隻會幫助您進行下一次部署。

對於此部署你可以嘗試這樣做(我從來沒有這樣做過,但理論上它可以工作):

  1. 複製新的DLL到子文件夾的地方
  2. 添加一個命令line xcopy命令到RunOnce registry key將新的dll從子文件夾複製到最終的exe文件夾中您想要的位置。
  3. 重新啓動。

RunOnce鍵包含命令行命令,它們在重新啓動時運行一次,然後從註冊表中刪除,以便它們不會再次運行。這就是InstallShield如何允許您在其他應用程序正在使用時覆蓋某些dll的方式。

0

本課程將重新命名當前運行的可執行文件,如果它完成無一例外,你可以簡單地寫入新的可執行文件,然後重新啓動,如:

Ourself.Rename(); 
// Download or copy new version 
File.Copy(newVersion, Ourself.FileName()); 
// Launch new version 
System.Diagnostics.Process.Start(Ourself.FileName()); 
// Close current version 
Close(); // Exit(); 

簡單就夠了嗎?

class Ourself 
{ 
    public static string FileName() { 
     Assembly _objParentAssembly; 

     if (Assembly.GetEntryAssembly() == null) 
      _objParentAssembly = Assembly.GetCallingAssembly(); 
     else 
      _objParentAssembly = Assembly.GetEntryAssembly(); 

     if (_objParentAssembly.CodeBase.StartsWith("http://")) 
      throw new IOException("Deployed from URL"); 

     if (File.Exists(_objParentAssembly.Location)) 
      return _objParentAssembly.Location; 
     if (File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName)) 
      return System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName; 
     if (File.Exists(Assembly.GetExecutingAssembly().Location)) 
      return Assembly.GetExecutingAssembly().Location; 

     throw new IOException("Assembly not found"); 
    } 

    public static bool Rename() 
    { 
     string currentName = FileName(); 
     string newName = FileName() + ".ori"; 
     if (File.Exists(newName)) 
     { 
      File.Delete(newName); 
     } 
     File.Move(currentName, newName); 
     return true; 
    } 
} 
相關問題