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