2011-04-14 37 views
9

Trong chương trình của tôi, tôi tạo Com + đối tượng dynamicly (cuối ràng buộc) sử dụngCom + cuối ràng buộc C# 4.0

Type comObjectType = Type.GetTypeFromProgID(progId, true); 
object comObject = Activator.CreateInstance(comObjectType); 

Và sau đó gọi một trong những phương pháp sử dụng phản ánh

object result = comObjectType.InvokeMember(MethodToActivate, BindingFlags.InvokeMethod, null, comObjec, new object[] {....}); 

Nó hoạt động lớn về Net 1.1/2.0/3.5

Bây giờ tôi đang cố chạy cùng mã trên cùng một máy (Windows XP) được biên dịch cho .Net 4.0, nhưng tôi có một

Exception: Method 'System.__ComObject.{MethodName}' not found. 

Tôi có ngoại lệ đối với hầu hết các đối tượng Com + (không phải cho tất cả). Không ai biết vấn đề là gì? Tại sao tôi có ngoại lệ trong môi trường FW 4.0? Tôi nên làm gì để tránh nó?

Thanks a lot, Daniel

Sau một số cuộc điều tra hơn tôi đã phát hiện ra rằng một số + proxy Com được tạo ra như System._ComObject (đó là những bản xứ, tôi giả sử), và một số được tạo ra như System.Runtime.Remoting.Proxies._TransparentProxy (I nghĩ rằng đó là các đối tượng Net Com +). Lời gọi phương thức hoạt động tốt cho những người được tạo ra là System._ComObject và không hoạt động cho System.Runtime.Remoting.Proxies._TransparentProxy. Thực tế intersting nhất là trong .Net 2.0 tất cả các đối tượng được tạo ra theo cùng một cách (_ComObject_TransparentProxy) nhưng lời gọi phương thức hoạt động tốt. Một thực tế thú vị là tôi có thể thấy phương pháp "mất tích" trong trình gỡ lỗi bằng reflecton

((System.EnterpriseServices.RemoteServicedComponentProxy)((((System.Runtime.Remoting.Proxies.__TransparentProxy)(ObjectToActivate)))._rp)).ProxiedType.GetMethods()

Tôi nghĩ đối với một số khoảnh khắc đó nó có thể là một vấn đề an ninh, nhưng tôi chạy các mã như WindowsService đăng nhập với tư cách là người dùng có đặc quyền của Quản trị viên

+0

Bạn đã kiểm tra bất kỳ sự cố 32/64-bit nào chưa? Có lẽ quá trình của bạn là 64-bit và do đó nhấn đăng ký COM 64-bit (nơi không có ai sống :-)? –

+0

Tôi không nghĩ rằng đó là một vấn đề 32/34-bit, máy địa phương của tôi là 32 bit, do đó, máy chủ từ xa –

+0

ok cho 32/64-bit. Bây giờ, có vẻ như máy chủ COM của bạn không phải là trong quá trình hoặc có một mô hình luồng cụ thể (do đó các proxy). Bạn có thể cung cấp thêm chi tiết về điều này không? chúng được lưu trữ ngoài quy trình chưa? Trong các dịch vụ thành phần? Và những gì về các đối số Invoke? bạn có chắc chắn không có sự mơ hồ? Điều gì về các BindingFlags? bạn không cần Public | –

Trả lời

6

Tôi đã phát hiện ra rằng có sự khác biệt giữa .NET FW trong tạo kiểu COM, và theo như tôi hiểu sự khác biệt chỉ tồn tại đối với các đối tượng .NET COM. Khi các loại đối tượng COM được tạo ra với

Type comObjectType = Type.GetTypeFromProgID(progId, true); 

kiểu dữ liệu muốn trả lại trong .NET 1.1/2.0/3.5 là loại NET thực tế của đối tượng, vì vậy không có vấn đề trong phương pháp gọi của nó, nhưng trong .NET 4.0 loại System.__ComObject được trả lại để mã

result = comObjectType.InvokeMember(
    MethodToActivate, BindingFlags.InvokeMethod, null, ObjectToActivate, InputParams); 

không thành công với phương pháp không tìm thấy ngoại lệ.

Các giải pháp mà tôi đã tìm thấy như sau:

Type comObjectType = Type.GetTypeFromProgID(progId, true);   
object comObject = Activator.CreateInstance(comObjectType); 

// here the real object type is returned 
Type acctualObjectType = comObject.GetType(); 
result = acctualObjectType.InvokeMember(
    "MethodToActivate", BindingFlags.InvokeMethod, null, comObject, InputParams); 

Mã này hoạt động tốt cho tất cả các môi trường.

+0

Thú vị - Tôi thực sự đã đăng câu trả lời trước đó mà tôi nghi ngờ sẽ giúp đỡ bằng cách mỉa mai xóa nó sau khi đọc một câu hỏi khác đã thuyết phục tôi rằng tôi đã sai - Dù sao, vui mừng bạn đã giải quyết vấn đề của mình – Justin

+0

Trong mã giải pháp của bạn, là 'comObject' được cho là giống với' ObjectToActivate'? –

+0

Vâng, ObjectToActivate là thuộc tính trả về comObject. –

1

Tôi không chắc chắn lý do tại sao mã trước đó của bạn không hoạt động nữa, tuy nhiên tôi tin rằng trong .Net 4.0 bạn có thể gọi phương thức COM bằng IDispatch/late binding qua loại dynamic - xem Does C# .NET support IDispatch late binding?.

+0

Tôi đã nghĩ về loại giải pháp này, nhưng không chấp nhận được cho tôi, bởi vì tôi cần cùng một mã chạy cho tất cả các phiên bản Net FW. Nó là một phần của thư viện lõi chạy trong các môi trường khác nhau –

+0

@Daniel: Bất kể nó có thỏa đáng hay không, việc sử dụng 'dynamic' vẫn hiển thị lỗi? – Gabe

+0

Tôi đã thử một mẫu nhỏ với 'động', nó hoạt động (nhưng không ngạc nhiên với tôi (:) –