如何知道 OPC Server CLSID?
Posted
技术标签:
【中文标题】如何知道 OPC Server CLSID?【英文标题】:How to know an OPC Server CLSID? 【发布时间】:2013-10-24 14:40:54 【问题描述】:我正在尝试通过 openscada 连接到 OPC 服务器。
我已经知道 MatrikonOPC explorer 提供的 OPC 服务器程序 ID,但连接不工作可能是由于 DCOM 配置错误。在继续之前,我想尝试通过服务器 CLSID 进行连接。
如何找到 OPC 服务器 CLSID?
【问题讨论】:
【参考方案1】:可能还有其他方法可以找到它,但我终于在这个论坛帖子中自己找到了答案:
http://www.control.com/thread/1026190171
如果您使用的是 Windows,请打开 regedit: 开始->运行->输入“regedit”+回车
搜索 VendorName.OPC.Name.1
类型的 OPC 服务器程序 ID (ProgID)。
示例:Matrikon.OPC.Universal.1
您会在注册表中找到多个条目,但在 My Computer\HKEY_CLASSES_ROOT\VendorName.OPC.Name.1
部分中,您将看到包含搜索到的 CLSID 的 CLSID
目录。
【讨论】:
【参考方案2】:您可以使用Prosys OPC Client 浏览服务器。它将为您显示所选服务器的 CLSID,您可以将其复制到剪贴板。
可以在本地使用注册表来查找 CLSID。远程您很少能访问注册表,但客户端应用程序可以为此使用 OpcEnum。
通常,如果您尝试远程连接,如果应用程序尝试使用本地注册表将 ProgID 转换为 CLSID,则连接可能会因 ProgID 而失败。当本地未安装服务器时,此信息不可用。
【讨论】:
【参考方案3】:如果您使用的是 Windows 系统,
点击开始->运行->输入“dcomcnfg.exe”
扩展组件服务 -> 计算机 -> 我的电脑 -> DCOM 配置
然后找到您的 OPC Server 并右键单击,您将获得 OPC Server 的所有详细信息
【讨论】:
【参考方案4】:我不熟悉 OpenSCADA。但是我已经用 C++ 开发了 OPC 客户端。如果您正在寻找本地运行的 OPC 服务器的类 ID,您可以使用此函数:
CLSID clsid;
hr = CLSIDFromProgID(L"Matrikon.OPC.Simulation", &clsid);
printf("OPC Server clsid: %p %p %p %p%p%p%p%p%p%p%p\n", (void*)opcServerId.Data1, (void*)opcServerId.Data2, (void*)opcServerId.Data3, (void*)opcServerId.Data4[0], (void*)opcServerId.Data4[1], (void*)opcServerId.Data4[2], (void*)opcServerId.Data4[3], (void*)opcServerId.Data4[4], (void*)opcServerId.Data4[5], (void*)opcServerId.Data4[6], (void*)opcServerId.Data4[7]);
如果您要连接到安装在远程计算机上的 OPC 服务器,而该远程计算机尚未安装在本地,则必须创建与 OPCEnum 的连接(希望同时安装在本地和远程计算机上)。您可以在远程服务器上创建一个 COM 对象,它将 OPC 服务器名称转换为 CLSID。这是一些演示这一点的代码。
//the first part of an OPC client is to connect to the OPCEnum service on the remote machine so we can look up the clsid of the OPC Server (given as a string).
//This code should get a list of OPC servers on a remote or local machine assuming that OPCEnum is running.
const CLSID CLSID_OpcServerList = 0x13486D51,0x4821,0x11D2, 0xA4,0x94,0x3C, 0xB3,0x06,0xC1,0x0,0x0; // 0x50fa5e8c, 0xdfae, 0x4ba7, 0xb6, 0x9a, 0x8f, 0x38, 0xc2, 0xfd, 0x6c, 0x27 ; //0x13486D50,0x4821,0x11D2, 0xA4,0x94,0x3C, 0xB3,0x06,0xC1,0x0,0x0;
const IID IID_IOPCServerList = 0x13486D50,0x4821,0x11D2, 0xA4,0x94,0x3C, 0xB3,0x06,0xC1,0x0,0x0; //for some reason the interface IID is the same as the CLSID.
const IID IID_IOPCServerList2 = 0x9DD0B56C,0xAD9E,0x43EE, 0x83,0x05,0x48, 0x7F,0x31,0x88,0xBF,0x7A;
IOPCServerList *m_spServerList = NULL;
IOPCServerList2 *m_spServerList2 = NULL;
COSERVERINFO ServerInfo = 0;
ServerInfo.pwszName = hostName; //L"localhost";
ServerInfo.pAuthInfo = NULL;
MULTI_QI MultiQI [2] = 0;
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;
// Create the OPC server object and query for the IOPCServer interface of the object
HRESULT hr = CoCreateInstanceEx (CLSID_OpcServerList, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &ServerInfo, 1, MultiQI); // ,IID_IOPCServer, (void**)&m_IOPCServer);
//hr = CoCreateInstance (CLSID_OpcServerList, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServerList, (void**)&m_spServerList);
if (hr == S_OK)
printf("Part1 okay\n");
m_spServerList = (IOPCServerList*)MultiQI[0].pItf;
//m_spServerList2 = (IOPCServerList2*)MultiQI[1].pItf;
else
printf("Co create returned: %p\n",(void *)hr);
m_spServerList = NULL;
//qDebug() << (void *)REGDB_E_CLASSNOTREG;
//try and get the class id of the OPC server on the remote host
CLSID opcServerId;
CLSID clsid;
if (m_spServerList)
hr=m_spServerList->CLSIDFromProgID(serverName,&opcServerId);
m_spServerList->Release();
else
hr = S_FALSE;
opcServerId.Data1 = 0;
clsid.Data1 = 0;
//try to attach to an existing OPC Server (so our OPC server is a proxy)
if (hr != S_OK)
wprintf(L"Couldn't get class id for %s\n Return value: %p", serverName, (void *)hr);
else
printf("OPC Server clsid: %p %p %p %p%p%p%p%p%p%p%p\n", (void*)opcServerId.Data1, (void*)opcServerId.Data2, (void*)opcServerId.Data3, (void*)opcServerId.Data4[0], (void*)opcServerId.Data4[1], (void*)opcServerId.Data4[2], (void*)opcServerId.Data4[3], (void*)opcServerId.Data4[4], (void*)opcServerId.Data4[5], (void*)opcServerId.Data4[6], (void*)opcServerId.Data4[7]);
// Create the OPC server object and query for the IOPCServer interface of the object.
//Do it on the remote computer.
MultiQI [0].pIID = &IID_IOPCServer;
MultiQI [0].pItf = NULL;
MultiQI [0].hr = S_OK;
if (opcServerId.Data1)
hr = CoCreateInstanceEx (opcServerId, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &ServerInfo, 1, MultiQI);
else
hr = S_FALSE;
if (hr != S_OK)
m_IOPCServer = NULL;
printf("Couldn't create server.\n");
else
//CoCreateInstanceEx should have returned an array of pointers to interfaces. Since we only asked for 1, lets just get it.
m_IOPCServer = (IOPCServer*) MultiQI[0].pItf;
printf("Created remote OPC server.\n");
这里还有一些注释掉的代码,演示了如何枚举所有远程 OPC 服务器。有趣的是,您可以获得这些远程服务器的 CLSID,但我相信您必须在远程计算机上创建一个单独的 COM 对象,以便为这些服务器计算一个可读的名称。 (我研究了一下,但我自己不需要它,所以我忘记了它是哪个界面)。
//list all the OPC interfaces.
CLSID catid[2];
catid[0]=CATID_OPCDAServer10; //= CATID_OPCDAServer10; //OPC1.0
catid[1] = CATID_OPCDAServer20;
IOPCEnumGUID *pEnumGUID;
hr = m_spServerList->EnumClassesOfCategories(2, catid, 0, NULL, (IEnumGUID**)&pEnumGUID);
printf("Enum Result: %u", (void*) hr);
if (hr == S_OK)
//pEnumGUID->Reset();
GUID serverGUID;
ULONG numberServers = 8;
//pEnumGUID->Next(maxServers,serverGUIDs, &numberServers);
while ((hr = pEnumGUID->Next (1, &serverGUID, &numberServers)) == S_OK)
WCHAR* wszProgID;
hr = ProgIDFromCLSID (serverGUID, &wszProgID); //This probably won't work unless the same OPC server is installed locally.
printf("server: %ls \n",wszProgID);
CoTaskMemFree (wszProgID);
;
【讨论】:
这对我真的很有帮助——非常感谢!希望我能多次投票。 有一个函数IOPCServerList::GetClassDetails
似乎可以工作(用于从远程机器获取人类可读的 ProgID),即使本地没有安装相同的 OPC 服务器。以上是关于如何知道 OPC Server CLSID?的主要内容,如果未能解决你的问题,请参考以下文章
谁知道wincc opc server具体详细设置? 留下联系方式,教会200分奉上!