2013-10-16 951 views
3

我試圖通過openscada連接到OPC服務器。如何知道OPC服務器的CLSID?

我已經知道由MatrikonOPC瀏覽器給出的OPC服務器程序ID,但連接不起作用可能是由於錯誤的DCOM配置。在繼續前進之前,我想嘗試通過服務器CLSID進行連接。

如何找到OPC服務器的CLSID?

回答

2

很可能有其他的方法來找到它,但我終於找到了答案我自己在這個論壇主題:

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

如果您使用的是Windows,打開註冊表編輯器: 開始 - >運行 - >輸入「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。當服務器沒有在本地安裝時,ithis信息不可用。

4

如果您使用的是Windows系統,

點擊開始 - >運行 - >輸入 「DCOMCNFG.EXE」

展開組件服務 - >計算機 - >我的電腦 - > DCOM配置

然後找到你的OPC服務器,右鍵點擊你將得到你的OPC服務器的所有細節

2

我對OpenSCADA並不熟悉。不過,我用C++開發了OPC客戶端。如果你正在尋找一個類ID本地運行的OPC服務器,您可以使用此功能:如果要連接到安裝了尚未在本地安裝在遠程計算機上的OPC服務器

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]); 

,您必須創建一個到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); 
    }; 
} 
+0

這對我真的很有幫助 - 謝謝你們!希望我可以多次投票。 – Reunanen

+0

有一個函數'IOPCServerList :: GetClassDetails'似乎可以工作(用於從遠程計算機獲取可讀的ProgID),即使相同的OPC服務器沒有在本地安裝。 – Reunanen

相關問題