发表于:2003-05-06 10:38:00
10楼
其实很简单:
1. 使用OPC服务器浏览器对象
下面一段代码显示了利用IOPCServerList接口浏览本地或远程计算机中已安装的OPC数据访问服务器的方法,省略处理错误返回代码步骤
MULTI_QI mqi;
COSERVERINFO sin, *sinptr;
DWORD clsctx;
unsigned long c;
CLSID clsid;
IEnumGUID *pEnumGUID;
CLSID catid = CATID_OPCDAServer20;//OPC数据访问服务器2.0组件目录
IOPCServerList *gpOPC = NULL;
clsid = CLSID_OPCServerList;
// set up server info
sinptr = &sin;
sin.dwReserved1 = sin.dwReserved2 = 0;
sin.pwszName = szNodeName; // szNodeName为本地或远程计算机名
sin.pAuthInfo = 0;
clsctx = CLSCTX_REMOTE_SERVER;
// set up mqi
mqi.pIID = &IID_IOPCServerList;
mqi.hr = 0;
mqi.pItf = 0;
HRESULT hr = CoCreateInstanceEx(clsid, NULL, clsctx, sinptr, 1, &mqi);// 创建OPC服务器的浏览器对象
gpOPC =(IOPCServerList*)mqi.pItf; //获得IOPCServerList接口
// 查询OPC DA 2.0 组件目录接口指针
hr = gpOPC->EnumClassesOfCategories(1, &catid, 1, &catid, &pEnumGUID);
//获得支持OPC DA2.0数据服务器的CLSID
while (S_OK == pEnumGUID->Next(1, &clsid, &c))
{
LPOLESTR pszProgID;
LPOLESTR pszUserType;
hr = gpOPC->GetClassDetails(clsid, &pszProgID, &pszUserType);
//打印OPC数据服务器的有关信息
printf("ProgID = %ls, UserType = %ls\n", pszProgID, pszUserType);
CoTaskMemFree(pszProgID);
CoTaskMemFree(pszUserType);
}
// Free the interfaces
if(gpOPC) gpOPC->Release();
客户获得的clsid可以用来创建相应的OPC服务器。
2.枚举OPC服务器
在早先的版本里,OPC规范规定了用OPC子健来标识OPC服务器在注册表里的入口。客户必须按这个OPC子健进行浏览。这种方法效率较低,因为它要求浏览所有的CLSID条目,命名冲突也会时常发生。但这个方法比较简单,在OPC客户端程序中也有较多的应用,它不支持远程计算机。
HKEY hk = HKEY_CLASSES_ROOT;
TCHAR szKey[MAX_KEYLEN];
WCHAR wszServerName[100];
TCHAR szOPCName[100];
CLSID clsid;
USES_CONVERSION;
for(int nIndex = 0;::RegEnumKey(hk, nIndex, szKey, MAX_KEYLEN) == ERROR_SUCCESS; nIndex++)
{
HKEY hProgID;
TCHAR szDummy[MAX_KEYLEN];
if(::RegOpenKey(hk, szKey, &hProgID) == ERROR_SUCCESS)
{
LONG lSize = MAX_KEYLEN;
if(::RegQueryValue(hProgID, "OPC", szDummy, &lSize) == ERROR_SUCCESS)
wcscpy(wszServerName, T2W(szKey));
//获得OPC数据服务器的CLSID
HRESULT hr =::CLSIDFromProgID(wszServerName, &clsid );
::RegCloseKey(hProgID);
}
}
一般情况以上代码就可以枚举本机内的所有OPC服务器,还可以通过测试服务器对象是否支持连接点来判断它是否支持OPC DA 2.0。