OPC客户端分析 —— 服务器查询

上篇讲到了如何找到OPC服务器,具体执行是在enumServerList的函数中,获得执行IID_IOPCServerList2的实例。下面继续分析。

	MULTI_QI MultiQI[2] = { NULL };

	MultiQI[0].pIID = &IID_IOPCServerList;
	MultiQI[0].pItf = NULL;
	MultiQI[0].hr = S_OK;

	MultiQI[1].pIID = &IID_IOPCServerList2;
	MultiQI[1].pItf = NULL;
	MultiQI[1].hr = S_OK;

	if (FAILED(enumServerList(hostname, MultiQI, sizeof(MultiQI) / sizeof(MULTI_QI))))
	{
		_tprintf(_T("Failed in enumServerList\n"));

		CoUninitialize();
		exit(EXIT_FAILURE);
	}

	serverIdInfo serverIdList[10] = { NULL };
	USHORT index = 0;

	if (FAILED(listServers(serverIdList, sizeof(serverIdList) / sizeof(serverIdInfo), MultiQI, index)))
	{
		_tprintf(_T("Failed in listServers\n"));

		CoUninitialize();
		exit(EXIT_FAILURE);
	}

这里出现了另一个函数,listServers,基于OpcEnum.exe返回的类实例,通过DA的三个CATID(CATID_OPCDAServer10/20/30)来获得枚举类指针,如下面的pEnum。有了它循环一下获得各个OPC服务器的类,进一步获得相对应的OPC服务器的程序名和GUID等。

HRESULT listServers(serverIdInfo serverIdList[], USHORT count, MULTI_QI MultiQI[], USHORT& index)
{
	CLSID clsid, opcServerId;
	opcServerId.Data1 = 0;
	ULONG fetched;
	HRESULT hr = S_OK;

	LPOLESTR ppszProgID, ppszUserType, ppszVerIndProgID;

	CATID arrcatid[3];
	arrcatid[0] = CATID_OPCDAServer10;
	arrcatid[1] = CATID_OPCDAServer20;
	arrcatid[2] = CATID_OPCDAServer30;

	IOPCServerList *m_spServerList = (IOPCServerList*)MultiQI[0].pItf;
	IOPCServerList2 *m_spServerList2 = (IOPCServerList2*)MultiQI[1].pItf;

	if (m_spServerList2)
	{
		IOPCEnumGUID * pEnum = NULL;

		hr = m_spServerList2->EnumClassesOfCategories(sizeof(arrcatid), arrcatid, 0, NULL, &pEnum);

		if (pEnum)
		{
			while ((hr = pEnum->Next(1, &clsid, &fetched)) == S_OK && fetched)
			{
				hr = m_spServerList2->GetClassDetails(clsid, &ppszProgID, &ppszUserType, &ppszVerIndProgID);

				if (FAILED(hr)) {
					LPOLESTR stringID = NULL;
					StringFromCLSID(clsid, &stringID);

					_com_error err(hr);
					LPCTSTR errMsg = err.ErrorMessage();

					if (ppszProgID)
						CoTaskMemFree(ppszProgID);
					if (ppszUserType)
						CoTaskMemFree(ppszUserType);
					if (ppszVerIndProgID)
						CoTaskMemFree(ppszVerIndProgID);

					_tprintf(_T("Failed in GetClassDetails: %s clsid=%S\n"), errMsg, stringID);
					continue;
				}

				hr = m_spServerList2->CLSIDFromProgID(ppszProgID, &opcServerId);

				if (FAILED(hr))
					break;

				wcscpy_s(serverIdList[index].ppszProgID, MAXCHAR, ppszProgID);
				memcpy_s(&serverIdList[index].opcServerId, sizeof(GUID), &opcServerId, sizeof(GUID));

				CoTaskMemFree(ppszProgID);
				CoTaskMemFree(ppszUserType);
				CoTaskMemFree(ppszVerIndProgID);

				if (index + 1 < count)
					index++;
				else
					break;
			}

			pEnum->Release();
		}
	}
	else if (m_spServerList)
	{
		IEnumCLSID * pEnum = NULL;

		hr = m_spServerList->EnumClassesOfCategories(sizeof(arrcatid), arrcatid, 0, NULL, &pEnum);

		if (pEnum)
		{
			while ((hr = pEnum->Next(1, &clsid, &fetched)) == S_OK && fetched)
			{
				hr = m_spServerList->GetClassDetails(clsid, &ppszProgID, &ppszUserType);

				if (FAILED(hr)) {
					LPOLESTR stringID = NULL;
					StringFromCLSID(clsid, &stringID);

					_com_error err(hr);
					LPCTSTR errMsg = err.ErrorMessage();

					if (ppszProgID)
						CoTaskMemFree(ppszProgID);
					if (ppszUserType)
						CoTaskMemFree(ppszUserType);

					_tprintf(_T("Failed in GetClassDetails: %s clsid=%S\n"), errMsg, stringID);

					continue;
				}

				hr = m_spServerList->CLSIDFromProgID(ppszProgID, &opcServerId);

				if (FAILED(hr))
					break;

				wcscpy_s(serverIdList[index].ppszProgID, MAXCHAR, ppszProgID);
				memcpy_s(&serverIdList[index].opcServerId, sizeof(GUID), &opcServerId, sizeof(GUID));

				CoTaskMemFree(ppszProgID);
				CoTaskMemFree(ppszUserType);

				if (index + 1 < count)
					index++;
				else
					break;
			}

			pEnum->Release();
		}
	}

	if (m_spServerList2)
		m_spServerList2->Release();

	if (m_spServerList)
		m_spServerList->Release();

	return hr;
}

下篇再给点干货,看下读写操作的执行。

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值