当前位置:首页 > 行业动态 > 正文

com进程內服务器

com进程内服务器是指在COM(组件对象模型)架构中,运行在与调用进程相同地址空间内的服务器组件。

定义与特点

1、定义:COM进程内服务器是指在DLL(动态链接库)中实现的COM服务器,它被加载到使用它的客户端应用程序的进程空间中,与客户端程序运行在同一个进程内。

2、特点

高效性:由于进程内服务器与客户端在同一进程空间中运行,它们之间的通信就像普通函数调用一样快速,不需要跨越进程边界进行参数传递和结果返回,因此执行效率非常高。

共享资源:进程内服务器可以直接访问客户端进程的资源,如内存、句柄等,这使得在一些需要共享大量数据或频繁交互的场景下具有优势。

部署方便:进程内服务器以DLL的形式存在,只需将DLL文件复制到客户端应用程序所在的目录或系统目录下即可使用,无需像进程外服务器那样单独安装和配置可执行文件。

工作原理

1、注册:进程内服务器必须在系统的注册表中进行注册,通常是在HKEY_CLASSES_ROOTCLSID键值下创建一个以服务器的GUID为名称的键,该键必须包含服务器的位置(DLL文件的路径)和线程模型等信息。

2、接口暴露:进程内服务器需要导出一个名为DllGetClassObject()的函数,这是COM库调用的第一个函数,用于获取服务器的类工厂对象,类工厂对象实现了IClassFactory接口,通过该接口可以创建服务器的具体实例。

com进程內服务器

3、对象创建:当客户端应用程序调用CoCreateInstance()函数创建COM对象时,COM库会根据注册表中的信息找到对应的进程内服务器DLL,并调用其DllGetClassObject()函数获取类工厂对象,然后通过类工厂对象的CreateInstance()方法创建具体的COM对象实例,并将其接口指针返回给客户端应用程序。

4、接口调用:客户端应用程序获得COM对象的接口指针后,就可以通过该接口调用进程内服务器提供的各种方法和服务,在调用过程中,由于客户端和服务器在同一进程内,所以可以直接进行函数调用和参数传递。

生命周期管理

1、加载与卸载:当客户端应用程序第一次使用进程内服务器时,操作系统会将服务器DLL加载到客户端进程的地址空间中,当不再需要服务器时,COM库会调用DllCanUnloadNow()函数询问服务器是否可以卸载,如果服务器确定不再被使用时,可以返回S_OK让COM库将其从内存中卸载。

2、引用计数:COM对象采用引用计数的方式来管理其生命周期,每当客户端创建一个COM对象实例时,引用计数就会增加;当客户端释放一个COM对象实例时,引用计数就会减少,当引用计数降为零时,表示没有客户端再使用该COM对象,此时COM对象会自动销毁自己。

示例代码

下面是一个简单的进程内服务器示例代码,展示了如何用C++编写一个基本的COM服务器:

com进程內服务器

文件名 代码内容
SimpleCOMServer.h cpp
[uuid(YOUR_SERVER_UUID)]
interface ISimpleComServer;
[uuid(YOUR_CLASS_UUID)]
class SimpleComServer : public ISimpleComServer {
public:
SimpleComServer();
virtual ~SimpleComServer();
// IUnknown methods
ULONG AddRef();
ULONG Release();
HRESULT QueryInterface(REFIID riid, void ppv);
// Custom method
HRESULT SayHello([in] BSTR name, [out, retval] BSTR response);
};
SimpleCOMServer.cpp cpp #include "SimpleCOMServer.h"
// Implementation of IUnknown methods
ULONG SimpleComServer::AddRef() {
return InterlockedIncrement((LONG)&m_dwRef);
}
ULONG SimpleComServer::Release() {
if (--m_dwRef == 0) {
delete this;
return 0;
}
return m_dwRef;
}
HRESULT SimpleComServer::QueryInterface(REFIID riid, void ppv) {
if (riid == IID_IUnknown) {
ppv = (IUnknown)this;
} else if (riid == IID_ISimpleComServer) {
ppv = (ISimpleComServer)this;
} else {
ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// Constructor and destructor
SimpleComServer::SimpleComServer() : m_dwRef(1) {}
SimpleComServer::~SimpleComServer() {}
// Implementation of custom method
HRESULT SimpleComServer::SayHello(BSTR name, BSTR response) {
use namespace _bstr_t;
response = SysAllocString(L"Hello, ");
response += name;
return S_OK;
}
SimpleCOMServer.def cpp LIBRARY "SimpleCOMServer"
EXPORTS
DllGetClassObject PRIVATE
DllRegisterServer INIT_INSTANCE
DllUnregisterServer TERMINATE_INSTANCE
DllInstall INSTALL_INIT_INSTANCE_FUNCTION
DllCanUnloadNow INSTANCE_METHOD
SimpleCOMServer.rgs cpp [module]
component=SimpleCOMServer.def
[file]
file=SimpleCOMServer.dll, type=library, threadingModel=Apartment
[file]
file=SimpleCOMServer.h, type=include
[file]
file=SimpleCOMServer.cpp, type=code
SimpleCOMServer.rc cpp IDRC "SimpleCOMServer.rc"
"SimpleCOMServer.def"
SimpleCOMServer.cpp cpp #define INITGUID
#include "initguid.h"
#include "SimpleCOMServer.h"
STDMETHODIMP HRESULT DllGetClassObject(const CLSID& rclsid, const IID& riid, void ppv) {
if (rclsid == &GUID_NULL
rclsid == &GUID_SimpleComServer) {
ppv = new SimpleComServer();
} else {
ppv = NULL;
}
return ppv ? S_OK : E_NOINTERFACE;
}
STDMETHODIMP HRESULT DllCanUnloadNow() {
return g_uDllRefCount > 0 ? S_FALSE : S_OK;
}
STDMETHODIMP HRESULT DllRegisterServer() {
return RegisterServer(TRUE);
}
STDMETHODIMP HRESULT DllUnregisterServer() {
return RegisterServer(FALSE);
}
int g_uDllRefCount = 0;
int main() {
CoInitialize(NULL);
HRESULT hr = CoRegisterClassObject(&GUID_SimpleComServer, CLSCTX_INPROC_SERVER, NULL, DllGetClassObject, &g_uDllRefCount);
if (FAILED(hr)) {
CoUninitialize();
return -1;
}
WaitForSingleObject(GetCurrentProcess(), INFINITE);
CoUninitialize();
return 0;
}“
initguid.h cpp // This header is typically generated by the MIDL compiler based on the .idl file. It contains the definitions of the CLSID and IID values used in the server.
SimpleCOMServer.idl cpp import "oaidl.idl";
[uuid(YOUR_SERVER_UUID), version(1.0)]
interface ISimpleComServer : IUnknown {
HRESULT SayHello([in] BSTR name, [out, retval] BSTR response);
};
[uuid(YOUR_CLASS_UUID), helpstring("SimpleCOMServer Class")]
coclass SimpleComServer {
interface ISimpleComServer;
};

常见问题解答

1、什么是COM进程内服务器?

答:COM进程内服务器是指在DLL中实现的COM服务器,它被加载到使用它的客户端应用程序的进程空间中,与客户端程序运行在同一个进程内,这种服务器类型具有高效性和资源共享等优点,适用于轻量级的小型服务器场景。

2、如何创建一个简单的COM进程内服务器?

答:创建一个简单的COM进程内服务器需要以下几个步骤:

定义COM接口:使用MIDL或其他工具定义COM接口,包括接口的方法和参数。

com进程內服务器

实现接口:在C++类中实现COM接口的方法,包括IUnknown接口的三个方法(AddRef、Release、QueryInterface)以及自定义的接口方法。

编写DllGetClassObject函数:该函数用于返回类工厂对象的实例,类工厂对象负责创建COM对象。

注册COM服务器:在系统的注册表中注册COM服务器的CLSID、程序ID等信息。

编译和生成DLL文件:使用编译器将源代码编译生成DLL文件,并将DLL文件注册到系统中。