2010-07-09 30 views
5

Tôi biết rằng chúng tôi có thể sử dụng CoLoadLibrary và DllGetClassObject để nhận giao diện IClassFactory và nhận giao diện thành phần COM mà không cần đăng ký DLL.Có thể kích hoạt đăng ký miễn phí cho các máy chủ COM EXE (ngoài quy trình) không?

Nhưng còn thành phần COM trong EXE thì sao? Có cách nào mà tôi có thể nhận được một giao diện thành phần COM từ một máy chủ COM loại EXE bằng cách chỉ cung cấp một đường dẫn tập tin khác nhau?

Trả lời

3

Nếu bạn sử dụng thựcregistration free COM, bạn sẽ có thể làm việc này cho cả đối tượng COM trong và ngoài proc.

Như Sharptooth đã chỉ ra, bạn thực sự không sử dụng đăng ký miễn phí COM. Thay vào đó, bạn thực sự đang cuộn của riêng bạn bằng cách giả mạo các cuộc gọi COM sử dụng trong khi kích hoạt. Giải pháp của bạn CÓ THỂ làm việc nếu bạn kiểm soát cả ứng dụng của bạn và máy chủ COM mà bạn đang kích hoạt nhưng có khả năng thất bại.

+0

Tôi không chắc chắn đoạn đầu tiên là đúng như, trong bài viết nó liên kết đến, chỉ đề cập đến của các máy chủ EXE ngoài quy trình là để nói rằng họ không thể được sử dụng với COM đăng ký miễn phí. Chủ đề này cũng hữu ích và chỉ ra các vấn đề với ROT mà COM đăng ký miễn phí dường như bỏ qua để quản lý: http://social.msdn.microsoft.com/Forums/vstudio/en-US/3849f22d-c8b8-429e- a03a-37601411acec/registrationfree-exe-com-server- Dường như chỉ có các đối tượng COM cơ bản, trong quá trình (cũng không nâng cao) được hỗ trợ bởi cơ chế miễn phí và cho bất kỳ thứ gì lạ hơn bạn phải cuộn của riêng bạn . –

+0

Câu trả lời chỉ có liên kết thực sự tồi vì liên kết có xu hướng biến mất ... giống như câu trả lời trong câu trả lời này. – Stephane

1

Bạn có thể chuyển thành phần COM trong một cuộc gọi hàm, dưới dạng con trỏ. Vì vậy, giả sử bạn thực hiện một đối tượng trong EXE của bạn, và tải một đối tượng COM khác từ một DLL, bạn có thể truyền đối tượng dựa trên EXE cho đối tượng từ tệp DLL. Đối tượng được tải sẽ cần hỗ trợ giao diện có chức năng chấp nhận con trỏ, ví dụ:

interface ILoadedObject 
{ 
    HRESULT GiveObject(IUnknown *pObj); 
}; 

Nếu đối tượng DLL-based thực hiện điều đó, bạn có thể gọi nó từ EXE của bạn và vượt qua nó một đối tượng mà không được đăng ký bất cứ nơi nào, vì vậy không có cần phải đăng ký các đối tượng trong một EXE để đạt được điều này .

Yêu cầu duy nhất là thực hiện đúng IUnknown: không phá hủy đối tượng cho đến khi Release được gọi đúng số lần và đảm bảo rằng có thể sử dụng QueryInterface để chuyển giữa một bộ giao diện cố định trên đối tượng và truy vấn đó cho IUnknown luôn trả về cùng một địa chỉ.

Mặt khác, bạn có thể đăng ký EXE như một máy chủ của các đối tượng, nhưng điều đó giới thiệu rất nhiều phức tạp; COM đã bắt đầu chạy EXE và sau đó gửi tin nhắn thông qua hàng đợi tin nhắn Windows. Điều này chỉ được sử dụng rộng rãi cho OLE; nó có thể khá mỏng manh.

Cập nhật

Một giải pháp hoàn chỉnh hơn là để xác định một cách tiêu chuẩn để tạo ra một thể hiện của một kiểu đối tượng, nhưng để cho phép các EXE để xác định cách thức hoạt động. Các EXE sẽ thực hiện:

interface IComponent; 

interface IEnvironment : IUnknown 
{ 
    HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew); 
} 

Mỗi thành phần phải hỗ trợ giao diện này:

interface IComponent : IUnknown 
{ 
    HRESULT SetEnvironment(IEnvironment *pEnv); 
} 

Bây giờ, để có được những hành vi tiêu chuẩn nơi EXE muốn sử dụng registry để tìm thành phần, nó có thể thực hiện các CreateInstance phương pháp như sau:

HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew) 
{ 
    HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, 
        __uuidof(IComponent), (void **)&ppNew); 
    if (FAILED(hr)) 
     return hr; 

    (*ppNew)->SetEnvironment(this); 
    return S_OK; 
} 

Nhưng dĩ nhiên nó có thể thay đổi điều này và "tiêm" một số thành phần. Vì vậy, thay vì (hoặc ngoài) đăng ký, một tập tin cấu hình có thể được sử dụng. Hoặc (như bạn đã hỏi) EXE có thể có sẵn trong triển khai của một số thành phần:

Bởi vì mỗi thành phần được thông báo về môi trường khi nó được tạo ra, nó có thể sử dụng môi trường để tạo ra các thành phần thêm:

// inside some component: 
HRESULT Comp::SetEnvironment(IEnvironment *e) 
{ 
    m_env = e; // using a smart pointer for ref-counting 
    return S_OK; 
} 

// in some method of the component 

ComPtr<IComponent> button; 
m_env->CreateInstance(CLSID_Button, &button); 

// now query button for more useful interface... 

Vì vậy, bất cứ khi nào một thành phần được tạo ra, môi trường (được xác định trong EXE) có thể kiểm soát chính xác cách thức thực hiện thành phần được tìm thấy. Mọi sáng tạo đều đi qua EXE.

Điều này đôi khi được gọi là "tiêm phụ thuộc" hoặc "đảo ngược kiểm soát".

+0

Cảm ơn, tôi không biết tôi hiểu giải pháp của bạn bao nhiêu, có vẻ như đó là một cách khác: 1. bắt đầu EXE và đặt điểm đối tượng tại thành phần COM dựa trên DLL. 2. khi tôi cần sử dụng đối tượng EXE thực hiện thành phần, tôi sẽ nhận được nó thông qua các thành phần DLL mà thực hiện một container con trỏ chứa thành phần thực hiện trong các tập tin EXE. Tôi đã hiểu chưa? – Gohan

+0

Tôi nghĩ rằng tôi hiểu bạn và tôi tin rằng bạn đã có nó. –

2

Không, bạn không thể. Bạn cần thiết lập COM marshalling giữa chương trình của bạn và out-proc COM server. Để đạt được điều này, bạn phải gọi CoInitialize() và sau đó là CoCreateInstance() hoặc CoGetClassObject().

Đường dẫn bạn mô tả với máy chủ trong proc - gọi CoLoadLibrary() và sau đó DllGetClassObject() - thực tế là một hack bẩn - nó bỏ qua các cơ chế COM bình thường và vì vậy chẳng hạn marshalling sẽ khởi động ngay cả khi nó cần thiết để đáp ứng luồng yêu cầu về mô hình (công cụ STA/MTA). Như vậy là có thể hack bẩn vì một máy chủ trong proc là một DLL thường xuyên với một số chức năng nổi tiếng tiếp xúc. Điều tương tự là không thể đối với một máy chủ COM out-proc - bạn cần phải dựa vào COM trong trường hợp đó.

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