OPC DA客户端项目管理不正确的功能错误 < >我在QT5中为C++ COM API创建了一个简单的OPC DA客户端。 客户端连接到远程服务器,获取OPCServer指针,使用ItemMgt接口创建新的OPC组,当我尝试向组中添加项目时失败

OPC DA客户端项目管理不正确的功能错误 < >我在QT5中为C++ COM API创建了一个简单的OPC DA客户端。 客户端连接到远程服务器,获取OPCServer指针,使用ItemMgt接口创建新的OPC组,当我尝试向组中添加项目时失败,c++,qt,com,opc,C++,Qt,Com,Opc,错误消息是:功能不正确。 据我所见,IUnknown::QueryInterface可用于此pItemMgt,但ValidateItems、CreateEnumerator和AddItems调用会导致相同的错误函数错误。OPC服务器是一个QMS220模拟程序(Quadera)。 知道有什么问题吗? 这是我第一次尝试编写DCOM客户端,这段代码可能有很多错误。 qms220.h文件包含qms220模拟程序的CLSID。 重现问题的最短代码如下: #include "opcda.h&quo

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

#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());
}
#包括“opcda.h”
#包括“qms220.h”
#包括
#包括
#包括
静态无效显示状态(常量QString和消息、HRESULT代码);
IOPCServer*pOPCServer=nullptr;
IOPCItemMgt*pItemMgt=nullptr;
OPCHANDLE服务器组句柄;
bool initializeCOM()
{
HRESULT hr=coinitializex(nullptr,COINIT_APARTMENTTHREADED);
如果(失败(小时)){
showStatus(“COM初始化失败!”,hr);
返回false;
}
hr=共同初始化安全性(
NULL,//安全描述符
-1、//COM身份验证
NULL,//身份验证服务
NULL,//保留
RPC\u C\u AUTHN\u LEVEL\u DEFAULT,//默认身份验证
RPC\u C\u IMP\u LEVEL\u IMPERSONATE,//默认模拟
NULL,//身份验证信息
EOAC_NONE,//附加功能
空//保留
);
如果(hr==RPC\u E\u太迟){
showStatus(“RPC初始化太晚,忽略…”,hr);
}否则{
如果(失败(小时)){
showStatus(“共同初始化安全”,hr);
返回false;
}
}
返回true;
}
void deinitializeCOM()
{
coninitialize();
}
静态常量int接口计数=1;
bool connectToServer(常量QString和地址)
{
_bstr_t serverName=地址.toStdString().c_str();
协同服务器信息系统;
memset(&cs,0,sizeof(cs));
cs.pwszName=serverName;
多重齐齐[接口计数];
memset(qi,0,sizeof(qi));
qi[0]。pIID=&IID_IOPCServer;
HRESULT hr=CoCreateInstanceEx(
CLSID_QMG220SIMDA,
无效的
CLSCTX_服务器,
&政务司司长,
接口计数,
气
);
如果(失败(小时)){
showStatus(“CoCreateInstanceEx”,hr);
返回false;
}
pOPCServer=(IOPCServer*)(qi[0].pItf);
返回true;
}
void disconnectFromServer()
{
if(pOPCServer!=nullptr){
pOPCServer->Release();
pOPCServer=nullptr;
}
}
void showOPCStatus(常量字符串和消息,HRESULT hr)
{
if(pOPCServer!=nullptr){
LPWSTR缓冲区=空PTR;
HRESULT hr2=pOPCServer->GetErrorString(hr、LOCALE\u SYSTEM\u默认值和缓冲区);
如果(hr2!=S_正常){

qDebug()因此,根据Qt文档: toWCharArray创建一个以非空字符结尾的unicode字符串。 因此,更好的用法是: int size=itemId.towcharray(itemibuffer); itemIdBuffer[size]=L'\0'; accessPathBuffer也是如此。 向OPC服务器发送未终止的组名可能不是一个好主意。 好的是,CreateGroupEnumerator发回与接收到的相同的未终止的组名。
因此,问题与COM或OPC无关,只是没有阅读好的文档。

这似乎100%特定于此QMS api,而不是COM本身。唯一特定于QMS的东西是Hardware.Modules.analyzer.SI220.SimulationMode。其他一切都只是使用COM的OPC DA。程序输出是:
code
“OPCServer::AddGroup”:“操作已成功完成。\r\n”服务器组句柄为:“0x1059698”修改后的更新率为:0“createMidGroup/AddItems”“:”“函数不正确。\r\n“createMidGroup/AddItems[0]”:”“未指定错误\r\n"
code
我不知道在这种情况下不正确的函数意味着什么。99%的代码是特定于QMS的。您调用的特定于QMS的方法返回错误,这与COM无关。先生,您是对的!我已将opc服务器类id更改为Softing Toolbox DA Demo server,并将属性更改为time.local.hour,相同的代码现在运行时没有错误(只是将更新率更改为10)。AddItems函数应该返回S_OK、E_FAIL、E_OUTOFMEMORY、E_INVALIDARG或S_FALSE,但不是error_INVALID_函数。谢谢您的回答。