我正在尝试通过openscada连接到OPC服务器。
我已经知道MatrikonOPC资源管理器提供的OPC服务器程序ID,但连接不起作用可能是由于错误的DCOM配置。在进一步讨论之前,我想尝试通过服务器CLSID进行连接。
如何查找OPC服务器CLSID?
答案 0 :(得分:4)
如果您使用的是Windows系统,
点击开始 - >运行 - >输入“dcomcnfg.exe”
展开组件服务 - >计算机 - >我的电脑 - > DCOM配置
然后找到您的OPC服务器并右键单击,您将获得OPC服务器的所有详细信息
答案 1 :(得分:3)
我不熟悉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);
};
}
答案 2 :(得分:2)
可能有其他方法可以找到它,但我终于在这个论坛帖子中找到了答案:
http://www.control.com/thread/1026190171
如果您使用的是Windows,请打开注册表: 开始 - &gt;运行 - &gt;输入“regedit”+输入
搜索VendorName.OPC.Name.1
类型的OPC服务器程序ID(ProgID)。
示例:Matrikon.OPC.Universal.1
您会在注册表中找到几个条目,但在My Computer\HKEY_CLASSES_ROOT\VendorName.OPC.Name.1
部分中,您将看到一个包含搜索到的CLSID的CLSID
目录。
答案 3 :(得分:2)
您可以使用Prosys OPC Client浏览服务器。它将为您显示所选服务器的CLSID,您可以将其复制到剪贴板。
可以在本地使用注册表来查找CLSID。远程地,您很少有权访问注册表,但客户端应用程序可以使用OpcEnum。
通常,如果您尝试远程连接,如果应用程序尝试使用本地注册表将ProgID转换为CLSID,则连接可能会失败并显示ProgID。当服务器未在本地安装时,ithis信息不可用。