2012-01-26 32 views
11

Tôi đang cố gắng dỡ bỏ một tệp DLL của bên thứ ba không đúng cách khỏi tiến trình .NET của tôi, vì nó dường như đang gây ra sự cố luôn được giải quyết bằng cách khởi động lại ứng dụng của tôi. Thay vì khởi động lại ứng dụng, tôi muốn loại bỏ và tải lại DLL thay thế.Buộc dỡ bỏ DLL khỏi assembly

DLL đang được tải bằng cách sử dụng LoadLibrary và bị xóa bằng cách sử dụng FreeLibrary (sử dụng DllImport s được lấy từ trang web P/Invoke). Khi tôi gọi LoadLibrary() Tôi thấy DLL xuất hiện trong danh sách các DLL trong Process Explorer, và khi tôi gọi FreeLibrary() Tôi thấy DLL biến mất khỏi danh sách các tệp DLL - như mong đợi.

Tuy nhiên, khi tôi đã gọi hàm Initialize() của thư viện của bên thứ ba, FreeLibrary() không còn loại bỏ DLL khỏi danh sách, ngay cả khi tôi gọi phương thức Deinit() tương ứng trước đó. Gọi một chức năng khác trong thư viện không có vấn đề này. Tuy nhiên, tôi phải Initialise() thư viện trước khi sử dụng!

Tôi đã thử cách ly tệp DLL bằng cách tạo tệp bằng chính số AppDomain, sau đó dỡ miền này sau khi DLL được giải phóng.

Tôi không nhận được mã lỗi lại hoặc ngoại lệ từ Initialize() hoặc Deinit(), từ LoadLibrary() hoặc FreeLibrary() hoặc từ việc tạo hoặc dỡ các AppDomain.

tôi đã sử dụng đoạn mã sau để tạo ra các AppDomain và khởi:

string pathToDll = Assembly.GetExecutingAssembly().CodeBase; 
m_Domain = AppDomain.CreateDomain("MyAppDomain", null, new AppDomainSetup { PrivateBinPath = pathToDll }); 
m_Module = (ThirdPartyModule)m_Domain.CreateInstanceFromAndUnwrap(pathToDll, typeof(ThirdPartyModule).FullName); 
m_Module.Init(); 

Để deinitialise và dỡ bỏ các AppDomain:

m_Module.Free(); 
m_Module = null; 
if (m_Domain != null) 
{ 
    AppDomain.Unload(m_Domain); 
    m_Domain = null; 
} 

Cuối cùng, lớp học lắp ráp ThirdPartyModule tôi:

internal class ThirdPartyModule : MarshalByRefObject 
{ 
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern IntPtr LoadLibrary(string lpFileName); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    internal static extern bool FreeLibrary(IntPtr hModule); 

    public IntPtr Module { get; set; } 

    public ThirdPartyModule() 
    { 
     Module = LoadLibrary("Misbehaving.dll"); 
    } 

    public void Free() 
    { 
     FreeLibrary(Module); 
     Module = IntPtr.Zero; 
    } 

    // ... 
} 

Điều này có vẻ như nó sẽ hoạt động như Tôi mong đợi? Nếu không, có cách nào khác tôi có thể đảm bảo rằng DLL này là hoàn toàn unloaded bởi quá trình của tôi?

Edit: Thông tin thêm

  • Các DLL chứa mã gốc, có khả năng tổng hợp từ C/C++
  • Đáng tiếc là quá trình của tôi bị hạn chế việc sử dụng .NET 2 chỉ (vì vậy không có giải pháp WCF).
  • Tôi đang sử dụng WinXP Pro x64 SP2 nhưng giải pháp phải là XP, Win7 x32/x64 vv tương thích.
  • Các DLL được sử dụng để giao tiếp với một USB token
+0

là tệp DLL gốc DLL? – Yahia

+4

Bạn có thể chạy DLL trong một quá trình khác và giao tiếp với nó thông qua WCF. Bạn có thể chỉ đơn giản là giết toàn bộ quá trình khi bạn wan't để dỡ bỏ nó. – CodingBarfield

+0

@Yahia - vâng, tôi nghĩ đó là một DLL C/C++. –

Trả lời

4

Tôi muốn giới thiệu để thực hiện một quá trình riêng biệt (EXE) mà ra mắt ứng dụng của bạn và do đó tải các DLL.

Điều này cho phép bạn giết quá trình bất cứ khi nào cần ...

tôi thấy một số tùy chọn về cách giao tiếp - ví dụ:

  • bạn có thể sử dụng COM (nếu bạn thực hiện nó như một máy chủ COM out-of-process)
  • bạn có thể sử dụng bộ nhớ chia sẻ (rất hiệu suất cao, xem this cho một hương và this cho một wrapper NET 2)

vì bạn viết rằng phương pháp này phải phù hợp với một số phiên bản Windows và một số đi kèm với một tường lửa máy tính để bàn tôi sẽ kiềm chế fro m sử dụng bất cứ thứ gì "mạng" cho IPC.

Các vấn đề liên quan