2011-09-07 30 views
5

Làm thế nào để bạn buộc Excel (2007) VBA phát hành tham chiếu đến đối tượng máy chủ COM?Cách phát hành đối tượng COM Server inprocess từ Excel VBA

Tôi đã viết một máy chủ COM inprocess (Single instance DLL) trong Visual Foxpro 9 SP2 được khởi tạo từ mã Excel 2007 VBA trên máy phát triển của tôi. Excel có vẻ đang giữ một tham chiếu đến đối tượng COM/dll ngay cả khi tôi đặt nó = Không có gì. Điều này ngăn cản tôi xây dựng lại DLL do một "Truy cập tập tin bị từ chối TestCOM.dll" tin nhắn cho đến khi tôi thoát khỏi Excel mà là một nỗi đau mỗi khi tôi muốn thực hiện một sự thay đổi và thử nghiệm nó.

Tôi đã luộc mã xuống để thiết lập thử nghiệm rất đơn giản: Dự án VFP9 (TestCOM) có chỉ là một tập tin .prg với các nội dung sau

DEFINE CLASS TestClass As Session OLEPUBLIC 

ENDDEFINE 

Bộ luật VBA như sau:

Sub Test() 

    Set objTest = CreateObject("TestCOM.TestClass") 
    Set objTest = Nothing 

End Sub 

Tôi đã thử xóa tham chiếu đến thư viện máy chủ COM trong dự án VBA nhưng điều này không tạo ra bất kỳ sự khác biệt nào. Tôi đã thử và không có DIMing các biến đối tượng và nó không có sự khác biệt. Tôi đã thử tạo một dự án VFP DLL mới nhưng vấn đề vẫn tồn tại.

Nếu tôi xây dựng ứng dụng VFP/dll như là một INPROCESS/DLL và chạy mã VBA tôi nhận được vấn đề này nhưng nếu tôi xây dựng nó như là một OUTOFPROCESS/EXE và chạy mã VBA tôi không nhận được vấn đề này.

Tôi tìm thấy một vấn đề rất giống nhau trong COM Object Cleanup ngoại trừ máy chủ COM của tôi được viết bằng Visual Foxpro 9 SP2 trong khi đó có liên quan đến C# và OP không giải thích chi tiết cách họ giải quyết vấn đề vì vậy tôi không biết cách đi xung quanh nó; nếu điều đó thậm chí còn có thể.

+0

Đối với bất kỳ người khác đọc chủ đề này sau đó tôi đã nhận ra rằng nếu dự án được xây dựng như một ra khỏi quá trình (EXE) COM Server thì bạn chỉ có thể xây dựng lại dự án mà không bỏ Excel nếu bạn không có tham chiếu đến thư viện kiểu trong VBA/Excel. – Caltor

Trả lời

6

Quy trình được sử dụng để khởi tạo lớp COM của bạn từ mã trong DLL của bạn là Excel gọi lớp thư viện COM để tìm việc triển khai của bạn bằng cách sử dụng ProgID hoặc ClassID. Khi bạn có một máy chủ inproc điều này có nghĩa là nó tìm thấy một đường dẫn đến DLL của bạn và sử dụng LoadLibrary để tải nó vào quá trình khách hàng của bạn và sau đó tạo ra các nhà máy lớp và các phương thức gọi trong DLL. Vì vậy, kết quả cuối cùng là Excel gọi LoadLibrary trên DLL của bạn và điều này khóa tập tin cho đến khi Excel gọi FreeLibrary trên tay cầm.

Sử dụng giao diện COM mà bạn không có quyền kiểm soát điều này. Bạn gọi CoCreateInstance() (hoặc từ VBA bạn tạo đối tượng với New hoặc CreateObject gọi API Win32 này bên dưới). Việc thực hiện điều này xử lý LoadLibrary và mọi thứ khác cho đến khi bạn nhận được giao một con trỏ giao diện để làm việc với. Một số ứng dụng sẽ định kỳ gọi CoFreeUnusedLibraries() để cố gắng phát hành các tập tin COM đã tải mà hiện không được sử dụng. Việc triển khai thực hiện lớp mặc định duy trì một bộ đếm các đối tượng được tạo có thể được sử dụng để xác định xem một DLL có đang được sử dụng hay không - nhưng điều này không phải lúc nào cũng đáng tin cậy vì các nhà văn lớp COM có thể không tuân thủ các quy tắc. Thoát khỏi Excel rõ ràng sẽ giải phóng khóa trên tệp.

Khi bạn tạo lớp COM của mình làm máy chủ quá trình - nó tồn tại trong một tệp thực thi riêng biệt hoặc DLL có thời gian tồn tại được quản lý khác nhau. Excel không còn giữ một khóa trên DLL và phát hành cá thể COM cũng có thể cho phép quá trình lưu trữ thoát ra.

Bạn có thể chuyển đổi một DLL được sử dụng làm máy chủ cục bộ (ngoài quy trình) bằng cách sắp xếp để nó được lưu trữ bởi DllHost. Nếu bạn sử dụng tiện ích OleView và tìm lớp ProgId của bạn thì bạn có thể kích hoạt lưu trữ trong một tiến trình thay thế (dllhost). Nó đã được một thời gian kể từ khi tôi đã làm điều đó nhưng cần có thông tin trên web về việc sử dụng lưu trữ thay thế. Rõ ràng lưu trữ một đối tượng COM out-of-process làm cho tất cả mọi thứ chậm hơn và giới thiệu tiềm năng cho các vấn đề marshalling khác nhau.Miễn là bạn giữ cho các giao diện tương thích oleautomation nó sẽ được sử dụng tốt.

+0

Cảm ơn bạn đã trả lời kỹ thuật chi tiết tuyệt vời của bạn. Vì vậy, trong ngắn hạn bạn về cơ bản nói rằng với các giao diện COM tôi đang ở lòng thương xót của khách hàng, trong trường hợp này Excel, và không có cách nào tôi buộc một phát hành của DLL? Tôi cần phải có đề cập trong câu hỏi của tôi rằng vấn đề này không xảy ra khi máy chủ COM được gọi là từ một bản sao của VFP do đó, lỗi dường như được với khách hàng chứ không phải là máy chủ. Tôi nghĩ rằng như một workaround tôi sẽ xây dựng dự án này như là một máy chủ Out of Process (EXE) trong quá trình phát triển và sau đó chuyển nó sang In Process (DLL) để thử nghiệm và phát hành cuối cùng. – Caltor

+2

Một thành phần phụ là bắt buộc. Máy chủ COM phải trả về S_OK từ điểm nhập DllCanUnloadNow() của nó. Không đơn giản để thử nghiệm trong môi trường VBA + Foxpro. –

1

Thêm một câu trả lời ngắn ....

Giải phóng DLL là vấn đề có nhiều nút và một quen thuộc đối với các nhà phát triển của trong quá trình COM thành phần để sử dụng trong Excel.

Có hai điều kiện mà cần phải được thỏa mãn

1) Không sử dụng một đầu tài liệu tham khảo thư viện liên kết (Tools-> Reference), sử dụng vào cuối ràng buộc để thay thế. Tham chiếu công cụ ràng buộc sớm sẽ giữ một khóa.

2) Gọi CoFreeUnusedLibraries để hủy COM máy chủ không còn có khách hàng.

Từ mã mẫu của bạn, bạn đã bị ràng buộc trễ nhưng vui lòng kiểm tra tham chiếu của bạn. Trong khi điểm 2) được gọi trong số payyhoyts answer không có mã nào được cung cấp.

Đây là một bản sao và khai pasteable

Private Declare Sub CoFreeUnusedLibraries Lib "ole32.dll"() 
Các vấn đề liên quan