2010-02-25 19 views
12

Tôi có một assembly .exe và một tập hợp các assembly được tham chiếu mà tôi muốn có thể triển khai mã cập nhật cho. Tôi không cần phải thực sự thay đổi mã đang chạy, nhưng lần sau tôi khởi chạy tệp thực thi, tôi muốn nó nhận mã được cập nhật. Hiện tại khi tôi cố gắng sao chép qua tệp đang chạy, tôi nhận được lỗi về .exe đang được sử dụng bởi một quy trình khác.Làm thế nào để cập nhật một assembly cho một tiến trình đang chạy C# (triển khai hot AKA)?

Để tóm tắt; làm thế nào tôi có thể cập nhật mã trong khi .exe đang được sử dụng?

+0

Dường như có một dự án trên Codeplex nhằm triển khai nóng cho .NET. Tôi đã không thử nó mặc dù: http://hotdeploy.codeplex.com/ –

Trả lời

17

Thật dễ dàng để thực hiện. Bạn có thể đổi tên tệp, Windows có khóa trên tay cầm chứ không phải mục nhập thư mục cho tệp. Bây giờ bạn chỉ có thể sao chép cập nhật mà không có vấn đề gì. Tất cả những gì còn lại cần làm là loại bỏ tệp được đổi tên sau khi ứng dụng của bạn khởi động lại. Nếu cần.

+0

Bạn có thể cung cấp thêm chi tiết/mã? – Jerry

+0

Ngoài câu trả lời của bạn, bạn có thể cần lưu ý rằng người dùng có thể cần phải tách khỏi quá trình gỡ lỗi trước khi đổi tên tệp, nếu không IDE (tức là Visual Studio) sẽ không cho phép nguồn được chỉnh sửa. –

+0

nó là giải pháp tồi vì bạn sẽ nhận được các phím tắt bị hỏng sau khi đổi tên. Bạn nên sử dụng ứng dụng trợ giúp thay thế. – l0pan

3

Tôi không nghĩ điều này là có thể. Ví dụ, khi triển khai các ứng dụng asp.net với thời gian ngừng hoạt động bằng 0, thực hành tốt nhất là có một bộ cân bằng tải để bạn có thể gỡ xuống một cá thể, cập nhật nó, sau đó lấy cái kia để cập nhật.

2

Bạn không thể cập nhật lắp ráp khi nó đang được sử dụng. Tùy chọn tốt nhất cho loại tình huống này là tạo ra một tệp thực thi nhỏ có bản sao bóng của các hội đồng của bạn và khởi chạy chúng từ một vị trí mới.

Bằng cách này, khi người dùng khởi chạy chương trình, bạn có thể sao chép bản sao (cục bộ) từ trang web triển khai, luôn có thể bị ghi đè.

2

ClickOnce cung cấp cho bạn một số tùy chọn. Có update strategy của "cập nhật sau khi khởi động ứng dụng".

Đối với các trường hợp phức tạp hơn, có System.Deployment namespace. Ví dụ: bạn có thể thăm dò định kỳ các bản cập nhật trong ứng dụng của mình.

1

gì về những điều sau:

  1. Triển khai các exe vào một thư mục cập nhật.
  2. Bất cứ khi nào ứng dụng khởi động, nó sẽ kiểm tra thư mục cập nhật.
  3. Nếu nó không có sản phẩm nào, hãy thực hiện một chương trình sao chép
  4. Chương trình sao chép sau đó sẽ thay thế các exe hiện có với một trong các thư mục cập nhật
  5. Xóa bất cứ điều gì trong thư mục update
  6. Sau đó relaunch exe
1

Ý tưởng hay nhất sẽ là một trong những câu trả lời khác đã được đề xuất ... như sử dụng phân tách bằng MEF và hoặc ClickOnce. Tuy nhiên, những giải pháp đó sẽ không giúp bạn cho "triển khai này". Chúng yêu cầu bạn thực hiện các thay đổi đối với exe và hoặc tạo một dây đeo khởi động thực thi, điều này sẽ chỉ giúp bạn triển khai tiếp theo.

Đối này triển khai bạn có thể thử làm điều này (Tôi chưa bao giờ làm điều này trước đây, nhưng về mặt lý thuyết nó có thể làm việc):

  1. Sao chép mới của dll của bạn vào một thư mục con ở đâu đó
  2. Thêm một lệnh dòng xcopy lệnh để RunOnce registry key để sao chép dll mới từ thư mục con vào thư mục exe cuối cùng mà bạn muốn nó đi.
  3. Khởi động lại.

Phím RunOnce chứa các lệnh dòng lệnh Chạy khi khởi động lại, sau đó bị xóa khỏi sổ đăng ký để chúng không chạy lại. Đây là cách InstallShield cho phép bạn ghi đè lên một số dll trong khi chúng đang được sử dụng bởi các ứng dụng khác.

0

Lớp này sẽ đổi tên tập tin thực thi hiện đang chạy, nếu nó hoàn thành mà không có ngoại lệ, bạn chỉ có thể viết mới thực thi, rồi khởi chạy lại, ví dụ:

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(); 

Dễ dàng đủ?

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; 
    } 
} 
Các vấn đề liên quan