最近我在尝试编写一个OPC客户端,资料上写了必须要用到OPCENUM.exe,这个可执行文件是做什么的?又什么用?
OPCEnum.exe的主要作用是方便用户浏览本地或者远程计算机上的ProgID。安装了OPC基金会的OPC Core Components Redistributable以后,在安装文件夹下可以找到OPCEnum.exe的源码。通过源码分析,我们得知:
1、 OPCEnum.exe是由ATL开发的一个进程内的Windwos服务。实现服务的类是CServiceModule。所以在DCOM配置的时候,在标识里的“选择运行此应用程序的用户账户”可以设置为“系统账户”(仅用于服务)。
2、 内部有一个COpcServerList组件,它实现了IOPCServerList和IOPCServerList2接口。这2个接口作用类似,其中IOPCServerList2是IOPCServerList的改进型。主要是调用另外一个叫COMCAT.dll里的API函数来实现关键接口函数的。接口函数的定义在OPCComn.h里,主要如下:
virtual HRESULT STDMETHODCALLTYPE EnumClassesOfCategories(
/* [in] */ ULONG cImplemented,
/* [size_is][in] */ CATID rgcatidImpl[ ],
/* [in] */ ULONG cRequired,
/* [size_is][in] */ CATID rgcatidReq[ ],
/* [out] */ IOPCEnumGUID **ppenumClsid) = 0;
virtual HRESULT STDMETHODCALLTYPE GetClassDetails(
/* [in] */ REFCLSID clsid,
/* [out] */ LPOLESTR *ppszProgID,
/* [out] */ LPOLESTR *ppszUserType,
/* [out] */ LPOLESTR *ppszVerIndProgID) = 0;
virtual HRESULT STDMETHODCALLTYPE CLSIDFromProgID(
/* [in] */ LPCOLESTR szProgId,
/* [out] */ LPCLSID clsid) = 0;
下面给出具体的应用的范例:
void CServerGeneralPage::DisplayComponentCatList (HTREEITEM hParent, CATID catid)
{
HRESULT hr;
// 初始化COM库
hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
if (SUCCEEDED (hr))
{
IOPCServerList2 *pCat = NULL;
// 得到IOPCServerList2接口的指针
hr = CoCreateInstance (CLSID_OPCServerList,
NULL,
CLSCTX_SERVER,
IID_IOPCServerList2,
(void **)&pCat);
// 如果成功,枚举计算机上的ProgID
if (SUCCEEDED (hr))
{
IOPCEnumGUID *pEnum = NULL;
CATID arrcatid [1];
arrcatid [0] = catid;
//通过CLSID枚举OPC服务器组件程序
hr = pCat->EnumClassesOfCategories (
sizeof (arrcatid) / sizeof (CATID),//number of catids in the array that follows
arrcatid, // catid array
0,
NULL,
(IOPCEnumGUID**)&pEnum); // clsid enumerator for registered components under this category
if (SUCCEEDED (hr))
{
GUID guid;
ULONG fetched;
while ((hr = pEnum->Next (1, &guid, &fetched)) == S_OK)
{
// 通过CLSID获得ProgID
WCHAR *wszProgID;
hr = ProgIDFromCLSID (guid, &wszProgID);
if (SUCCEEDED (hr))
{
#ifdef _UNICODE
m_pServerList->InsertItem (wszProgID, ILI_COMPONENT, ILI_COMPONENT, hParent);
#else
TCHAR szProgID [DEFBUFFSIZE];
_wcstombsz (szProgID, wszProgID, sizeof (szProgID) / sizeof (TCHAR));
m_pServerList->InsertItem (szProgID, ILI_COMPONENT, ILI_COMPONENT, hParent);
#endif
// 释放字符资源
CoTaskMemFree (wszProgID);
}
}
pEnum->Release ();
}
pCat->Release ();
}
// 注销COM库
CoUninitialize ();
}
}