首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OPC DA客户端ItemMgt功能错误

OPC DA客户端ItemMgt功能错误
EN

Stack Overflow用户
提问于 2021-05-05 16:41:04
回答 1查看 100关注 0票数 0

我已经在Qt5中为C++ COM API创建了一个简单的OPC客户机。客户端连接到远程服务器,获取一个OPCServer指针,使用ItemMgt接口创建一个新的OPC组,当我尝试向该组中添加项目时,客户端将失败。

错误消息是:函数不正确。据我所知,IUnknown::QueryInterface适用于此pItemMgt,但ValidateItems、CreateEnumerator和AddItems调用会导致相同的不正确函数错误。OPC服务器是一个QMS220Simulator (Quadera)。你知道问题出在哪里吗?这是我第一次尝试编写DCOM客户端,所以这段代码可能会有很多地方出错。qms220.h文件包含QMS220Simulator的CLSID。重现该问题的最短代码如下:

代码语言:javascript
复制
#include "opcda.h"
#include "qms220.h"

#include <QApplication>
#include <QDebug>
#include <comdef.h>

static void showStatus(const QString &message,HRESULT code);

IOPCServer *pOPCServer = nullptr;
IOPCItemMgt *pItemMgt = nullptr;
OPCHANDLE serverGroupHandle;

bool initializeCOM()

{
    HRESULT hr = CoInitializeEx(nullptr,COINIT_APARTMENTTHREADED);
    if (FAILED(hr)) {
        showStatus("COM initialization failed!",hr);
        return false;
    }

    hr = CoInitializeSecurity(
                NULL, //security descriptor
                -1, //COM authentication
                NULL, //authentication services
                NULL, //reserved
                RPC_C_AUTHN_LEVEL_DEFAULT, //default authentication
                RPC_C_IMP_LEVEL_IMPERSONATE, //default impersonation
                NULL, //authentication info
                EOAC_NONE, //additional capabilities
                NULL //reserved
                );

    if (hr == RPC_E_TOO_LATE) {
        showStatus("RPC initalization is too late, ignoring...",hr);
    } else {
        if (FAILED(hr)) {
            showStatus("CoInitializeSecurity",hr);
            return false;
        }
    }

    return true;
}


void deinitializeCOM()
{
    CoUninitialize();
}


static const int INTERFACE_COUNT = 1;


bool connectToServer(const QString &address)
{
    _bstr_t serverName = address.toStdString().c_str();
    COSERVERINFO cs;
    memset(&cs,0,sizeof(cs));
    cs.pwszName = serverName;
    MULTI_QI qi[INTERFACE_COUNT];
    memset(qi,0,sizeof(qi));

    qi[0].pIID = &IID_IOPCServer;

    HRESULT hr = CoCreateInstanceEx(
                CLSID_QMG220SIMDA,
                NULL,
                CLSCTX_SERVER,
                &cs,
                INTERFACE_COUNT,
                qi
                );

    if (FAILED(hr)) {
        showStatus("CoCreateInstanceEx",hr);
        return false;
    }

    pOPCServer = (IOPCServer*)(qi[0].pItf);

    return true;
}

void disconnectFromServer()
{
    if (pOPCServer != nullptr) {
        pOPCServer->Release();
        pOPCServer = nullptr;
    }
}
void showOPCStatus(const QString &message,HRESULT hr)
{
    if (pOPCServer != nullptr) {
        LPWSTR buffer = nullptr;
        HRESULT hr2 = pOPCServer->GetErrorString(hr,LOCALE_SYSTEM_DEFAULT,&buffer);
        if (hr2 != S_OK) {
            qDebug() << message << QString(": HRESULT: 0x%1").arg(hr,8,16,QChar('0'));
        } else {
            qDebug() << message << QString(": ") << QString::fromWCharArray(buffer);
            CoTaskMemFree(buffer);
        }
    } else {
       qDebug() << message << QString(": HRESULT: 0x%1").arg(hr,8,16,QChar('0'));
    }
}

static const LPCWSTR MIDGROUPNAME = L"mid";

bool createMIDGroup()
{
    if (pOPCServer == nullptr) return false;

    OPCHANDLE clientGroupHandle = 1;
    DWORD revisedUpdateRate;

    HRESULT hr = pOPCServer->AddGroup(
                MIDGROUPNAME,
                FALSE, //active
                0, // requestedUpdateRate
                clientGroupHandle,
                NULL, //timebias
                NULL, //percentDeadBand,
                LOCALE_SYSTEM_DEFAULT, //lcid
                &serverGroupHandle,
                &revisedUpdateRate,
                IID_IOPCItemMgt,
                (LPUNKNOWN *)(&pItemMgt)
                );
    showOPCStatus("OPCServer::AddGroup",hr);
    if (hr != S_OK) return false;

    qDebug() << "The server group handle is: " << QString("0x%1").arg(serverGroupHandle,4,16);
    qDebug() << "The revised update rate is: " << revisedUpdateRate;


    #define ITEM_ID L"Hardware.Modules.Analyser.SI220.SimulationMode"
    QString accessPath("");
    QString itemId("Hardware.Modules.Analyser.SI220.SimulationMode");
    wchar_t accessPathBuffer[1024];
    wchar_t itemIdBuffer[1024];
    accessPath.toWCharArray(accessPathBuffer);
    itemId.toWCharArray(itemIdBuffer);
    static const int ITEM_COUNT = 1;

    OPCITEMDEF ItemArray[ITEM_COUNT] =
        {{
        /*szAccessPath*/ accessPathBuffer,
        /*szItemID*/ itemIdBuffer,
        /*bActive*/ FALSE,
        /*hClient*/ 1,
        /*dwBlobSize*/ 0,
        /*pBlob*/ NULL,
        /*vtRequestedDataType*/ VT_UI1,
        /*wReserved*/0
        }};

    OPCITEMRESULT *itemResults = nullptr;
    HRESULT *errors = nullptr;

    hr = pItemMgt->AddItems(ITEM_COUNT,ItemArray,&itemResults,&errors);

    bool failed = false;
    if (hr != S_OK) {
        failed = true;
    }

    showOPCStatus("createMidGroup/AddItems ",hr);

    for(DWORD k=0;k<ITEM_COUNT;k++) {
        showOPCStatus(QString("createMidGroup/AddItems[%1]").arg(k),errors[k]);
        if (errors[k] != S_OK) {
            failed = true;
        }
        CoTaskMemFree(itemResults[k].pBlob);
    }

    CoTaskMemFree(itemResults);
    CoTaskMemFree(errors);

    return !failed;
}

void removeMIDGroup()
{
    if (pOPCServer != nullptr) {
        if (pItemMgt != nullptr) {
            pItemMgt->Release();
            pItemMgt = nullptr;
        }

        HRESULT hr = pOPCServer->RemoveGroup(serverGroupHandle,false);
        if (hr != S_OK) {
            showStatus("deleteMIDGroup",hr);
        }
    }
}


int main(int argc, char *argv[])
{
    Q_UNUSED(argc)
    Q_UNUSED(argv)

    if (!initializeCOM()) return -1;
    if (connectToServer(QString("192.168.12.106"))) {
        if (createMIDGroup()) {
            removeMIDGroup();
        }

        disconnectFromServer();
    }


    deinitializeCOM();

    return 0;
}

static void showStatus(const QString &message,HRESULT code)
{
    _com_error error(code);

    qDebug() << message + QString(": " ) +  QString::fromWCharArray(error.ErrorMessage());
}
EN

回答 1

Stack Overflow用户

发布于 2021-05-06 19:23:29

因此,根据Qt文档:https://doc.qt.io/qt-5/qstring.html#toWCharArray toWCharArray创建了一个以非空字符终止的unicode字符串。因此更好的用法是: int size = itemId.toWCharArray(itemIdBuffer);itemIdBuffersize = L'\0';accessPathBuffer也是如此。向OPC服务器发送一个未终止的组名可能并不是一个好主意。好消息是,CreateGroupEnumerator发送回与接收到的相同的未终止的组名。所以这个问题既不是COM也不是OPC相关的,它只是没有阅读好的文档。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67397865

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档