3

我正在尝试通过 openscada 连接到 OPC 服务器。

我已经知道 MatrikonOPC explorer 给出的 OPC 服务器程序 ID,但连接不工作可能是由于错误的 DCOM 配置。在继续之前,我想尝试通过服务器 CLSID 进行连接。

如何找出 OPC 服务器 CLSID?

4

4 回答 4

6

如果您使用的是 Windows 系统,

点击开始 -> 运行 -> 输入“dcomcnfg.exe”

展开组件服务 -> 计算机 -> 我的电脑 -> DCOM 配置

然后找到您的 OPC Server 并右键单击,您将获得 OPC Server 的所有详细信息

于 2014-02-11T06:07:41.190 回答
3

可能还有其他方法可以找到它,但我终于在这个论坛帖子中自己找到了答案:

http://www.control.com/thread/1026190171

如果您使用的是 Windows,请打开 regedit:开始 -> 运行 -> 键入“regedit”+回车

搜索类型为 的 OPC 服务器程序 ID (ProgID) VendorName.OPC.Name.1

示例:Matrikon.OPC.Universal.1

您将在注册表中找到几个条目,但在该My Computer\HKEY_CLASSES_ROOT\VendorName.OPC.Name.1部分中,您将看到一个CLSID包含搜索到的 CLSID 的目录。

于 2013-10-16T13:55:18.667 回答
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);
    };
}   
于 2015-04-17T00:34:58.653 回答
2

您可以使用Prosys OPC 客户端浏览服务器。它将为您显示所选服务器的 CLSID,您可以将其复制到剪贴板。

可以在本地使用注册表来查找 CLSID。远程您很少能够访问注册表,但客户端应用程序可以为此使用 OpcEnum。

通常,如果您尝试远程连接,如果应用程序尝试使用本地注册表将 ProgID 转换为 CLSID,则连接可能会因 ProgID 而失败。当服务器未在本地安装时,此信息不可用。

于 2013-10-16T14:59:46.707 回答