c++优化破OLE自动化程序(非mfc)

C++ Optimization breaking OLE Automation program (non-MFC)

本文关键字:mfc 程序 自动化 优化 OLE c++      更新时间:2023-10-16

我正在编写一个程序来解析Word文档并使用OLE自动化(我猜是非mfc方式)将数据导出到Excel工作簿。在调试中工作良好,在发布中不是这样(特别是如果启用了优化)。错误是IDispatch::Invoke调用失败,特别是:

0x80020004 DISP_E_PARAMNOTFOUND Parameter not found

我检查了StackOverflow的一些建议,主要的似乎是未初始化的变量。可能就是这样,但我还是不明白这个具体的例子。我把它缩小到我的程序Automation::Dispatch::Invoke中的一个函数,它负责最终调用IDispatch::Invoke。传入Automation::Dispatch::Invoke的参数是正确的,所以问题是在其代码的某个地方。

查看我改编的基础代码(来自MSDN),我能够让它工作并缩小确切的问题线。下面显示的代码不工作,但注释指出了我移动使其工作的行(查找带有<--- Problem line注释的2行)。在调试模式下,这一行的位置无关紧要,它在任何位置都可以工作。


我的问题是这修复了什么,为什么它是一个问题开始?谢谢你,如果我能使问题更清楚,请告诉我。


HRESULT Automation::Dispatch::Invoke(int cmd, std::string name, std::vector<VARIANT> values)
{
  USES_CONVERSION;
  HRESULT result;
  /* Get DISPID for name passed */
  DISPID dispID;
  LPOLESTR nameOle=A2OLE(name.c_str());
  result=pObjectInt->GetIDsOfNames(IID_NULL, &nameOle, 1, LOCALE_USER_DEFAULT, &dispID);
  if (FAILED(result)) {
    return result;
  }
  /* Reverse elements in values vector so they are invoked in the correct order */
  std::reverse(values.begin(), values.end());
  /* Allocate memory for object values */
  VARIANT *pValues=new VARIANT[values.size() + 1];
  for (unsigned int i=0; i < values.size(); ++i) {
    pValues[i]=values[i];
  }
  /* Build DISPPARAMS */
  DISPPARAMS dispParams= {NULL, NULL, 0, 0};
  /* DISPID dispidNamed=DISPID_PROPERTYPUT;   <--- PROBLEM LINE moved here makes it work */
  dispParams.cArgs=values.size();
  dispParams.rgvarg=pValues;
  /* Handle special-case for property-puts */
  if (cmd==DISPATCH_PROPERTYPUT) {
    DISPID dispidNamed=DISPID_PROPERTYPUT;   /* <--- PROBLEM LINE here */
    dispParams.cNamedArgs=1;
    dispParams.rgdispidNamedArgs=&dispidNamed;
  }
  /* Make the call */
  if (cmd==DISPATCH_METHOD || cmd==DISPATCH_PROPERTYPUT) {
    result=pObjectInt->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, cmd, &dispParams, NULL, NULL, NULL);
  }
  else {
    VariantInit(&objectData);
    result=pObjectInt->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, cmd, &dispParams, &objectData, NULL, NULL);
  }
  delete[] pValues;
  return result;
}

在此代码中:

if (cmd==DISPATCH_PROPERTYPUT) {
    DISPID dispidNamed=DISPID_PROPERTYPUT;   /* <--- PROBLEM LINE here */
    dispParams.cNamedArgs=1;
    dispParams.rgdispidNamedArgs=&dispidNamed;
}

dispidNamed是它所在代码块(即由{ }分隔的区域)的局部变量。

到达}后,它就不存在了。那么rgdispidNamedArgs是一个悬空指针,因为它不再指向一个存在的变量。

在调试模式下,你很不幸,它没有更快地触发一个错误。