2011-01-14 20 views
5

Tôi có một máy chủ COM ngoài quy trình cần theo dõi mọi thứ. Máy chủ này hoạt động như một dịch vụ và là nội bộ, một singleton. Để đơn giản, tôi sẽ gọi anh ta là BossCom.Làm cách nào tôi có thể sắp xếp một tham chiếu COM ngoài quy trình trên các ranh giới quá trình?

Tôi có một máy chủ COM ngoài quy trình khác là nhân viên. Đó là, để ổn định hệ thống, một máy chủ sử dụng một lần (có nghĩa là nếu bạn tạo 2 WorkerCom, có 2 WorkerCom.exe đang chạy). Để đơn giản, tôi sẽ gọi anh ta là WorkerCom.

WorkerCom có ​​thể được bắt đầu bởi bất cứ điều gì, ngay cả khi chính nó nếu ai đó chạy anh ta thông qua dòng lệnh với các đối số dòng lệnh bên phải.

Mục tiêu tổng thể là để BossCom biết WorkerComs là gì, biết họ đang làm gì và có thể ra lệnh cho họ (tạm dừng, dừng, tăng tốc, v.v.).

Suy nghĩ ban đầu của tôi về điều này sẽ là bất cứ khi nào WorkerCom bắt đầu, ông sẽ CoCreateInstance một BossCom và gọi BossCom-> RegisterWorker (IUnknown me). Sau đó, khi WorkerCom sắp ngừng hoạt động, anh ta sẽ gọi BossCom-> UnregisterWorker (IUnknown me). BossCom có ​​thể QueryInterface IUnknown cho IWorkerCom và có thể ra lệnh.

Điều đó sẽ hoạt động tốt nếu tất cả các đối tượng com này nằm trong cùng một quy trình, nhưng chúng không hoạt động. Tôi đã nghĩ về việc sử dụng GlobalInterfaceTable, nhưng nó chỉ toàn cầu theo nghĩa của một quá trình đơn lẻ.

Tôi đã dành một vài ngày nghiên cứu vấn đề này và đang thua lỗ. Có lẽ tôi đang nhìn đường hầm.

Làm cách nào tôi có thể so sánh tham chiếu đến đối tượng com từ Công nhân với Boss? 2,, và, cho những gì nó có giá trị, BossCom được viết bằng C# và WorkerCom được viết bằng ATL C++ nhưng tôi sẽ có các giải pháp được viết bằng VB, Scala, Lisp, hoặc bất cứ điều gì. Tôi hình dung tôi có thể dịch ý tưởng cốt lõi. :-)

+3

Không này chỉ làm việc? Tôi thừa nhận tôi đã không làm bất cứ điều gì nhiều với COM, nhưng toàn bộ điểm của nó là out-of-process là bạn đã nhận được COM để cuộc gọi nguyên soái qua ranh giới quá trình, phải không? –

+0

Phải, đối với hầu hết mọi thứ, nhưng IUnknown chỉ là một con trỏ, phải không? Con trỏ "this" trong WorkerCom sẽ không có bất kỳ ý nghĩa nào trong quyền BossCom? Hay quá trình đầm lầy sẽ giữ được ý nghĩa. Tôi đoán tôi ít nhất nên thử nó. –

+2

Nó sẽ làm việc ra khỏi kệ cho là có proxy/stubs hoặc typelib để tạo điều kiện marshalling. Trong thực tế marshalling là chính xác cho điều đó - để cung cấp cho một khách hàng một đối tượng giả ("proxy") được nhân đôi với máy chủ. Nó hoạt động một cách minh bạch từ quan điểm mã. – sharptooth

Trả lời

2

Theo nhận xét, điều này thực sự làm việc ra khỏi hộp. Có một chi tiết bổ sung mặc dù điều đó làm cho nó hoạt động.

Ban đầu khi tôi đang xem xét các giao diện C# xử lý các giao diện sao chép, kiểu đối số là IntPtr. Vâng, một IntPtr chỉ là một thời gian dài vì vậy nó chuyển giá trị như là và, như vậy, không hoạt động.

Điều quan trọng là đặt thuộc tính MarshalAs trên đối số. Vì vậy, phương pháp RegisterWorker của tôi trông giống như sau:

public void RegisterWorker(
     [In, MarshalAs(UnmanagedType.IUnknown)] object ptr 
     ) 
    { 
     IWorkerCom worker = (IWorkerCom) ptr; 
     Workers.Add(worker); 
    } 

Hoàn toàn tuyệt vời.

1

Tôi phải làm điều gì đó tương tự gần đây và thấy rằng việc sử dụng bộ nhớ chia sẻ hoạt động rất tốt đối với tôi. BossCom có ​​thể tạo và sở hữu bộ nhớ dùng chung và người lao động có thể đăng ký bằng cách tạo một mục nhập trong bộ nhớ dùng chung. Đây là một số MSDN link đến những gì tôi đang nói đến. Hãy nhớ sử dụng một mutex để đồng bộ hóa quyền truy cập vào bộ nhớ ...

+0

Điều đó xử lý đăng ký ok, nhưng tôi không rõ ràng về cách giúp với lệnh và kiểm soát của người lao động. –

+0

Bộ nhớ dùng chung chỉ đơn giản là cách giao tiếp thông qua bàn phím. BossCom có ​​thể ghi các lệnh vào bộ nhớ và báo hiệu một sự kiện mà các công nhân chờ đợi. Có rất nhiều cách khác để làm điều này và tất cả phụ thuộc vào yêu cầu bảo mật của bạn. Tôi chỉ tìm thấy cách tiếp cận này rất nhanh để thực hiện và rất linh hoạt. – T33C

+0

Tôi đánh giá cao ý tưởng, nhưng UAC khiến việc này trở nên khó khăn hơn. Ứng dụng của tôi phải chạy trong Windows XP trở lên. API làm cho bộ nhớ chia sẻ có thể sử dụng trên các ranh giới người dùng UAC không tồn tại trong XP. Tôi đã làm việc xung quanh điều này trong quá khứ, nhưng tôi không mong muốn làm điều đó một lần nữa. –

1

Bạn có một chút hạn chế trong việc có thể tạo các giao diện marshalable trong C#. Không có cách nào dễ dàng để thiết lập proxy. Không có vấn đề như vậy trong ATL, khai báo một giao diện gọi lại trong IDL. Và chuyển một con trỏ cá thể bằng lệnh RegisterWorker(). Máy chủ sẽ lưu trữ nó cho đến khi nó nhận được cuộc gọi không đăng ký. Sử dụng giao diện gọi lại đó để tạo thông báo.

2

Bạn nên xem Monikers, được sử dụng để xác định cá thể đối tượng COM ngay cả trên các máy khác nhau.

+0

Điều này thật thú vị. Và nó sẽ có khả năng làm cho các phần khác của dự án của tôi dễ dàng hơn. Tôi nhớ đã làm việc với DirectShow, các biệt danh chỉ là chuỗi văn bản. Những người nên soái vô cùng dễ dàng. Heck, tôi thậm chí có thể đặt chúng trong một bảng ESE để bất cứ ai (giống như các công nhân khác) có thể tìm thấy chúng. Tìm kiếm nhanh không cho thấy cách tôi có thể tạo biệt danh cho đối tượng của mình. Bất kỳ con trỏ? –

+0

Có thể CreateObjrefMoniker? –