Я пишу программу для анализа Word-документа и экспорта данных в книгу Excel с использованием OLE Automation (как я полагаю, не-MFC). Хорошо работает в Debug, а не в Release (особенно если оптимизация включена). Ошибка в том, что IDispatch :: Invoke вызова не удалось, а именно:C++ Оптимизация, нарушающая программу OLE Automation (не-MFC)
0x80020004 DISP_E_PARAMNOTFOUND Parameter not found
Я проверил StackOverflow для некоторых предложений и главный один, кажется, неинициализированная. Это может быть то, что происходит, но я все еще не понимаю этот конкретный случай. Я сузил его до одной функции в своей программе Automation::Dispatch::Invoke
, которая отвечает за окончательное вызов IDispatch::Invoke
. Аргументы, передаваемые в Automation::Dispatch::Invoke
, верны, поэтому проблема находится где-то в его коде.
Глядя на базовый код (из MSDN), с которым я его адаптировал, я смог заставить его работать и сузить точную проблемную линию. Ниже показан код, который не работает, но комментарии указывают линию, которую я переместил, чтобы заставить ее работать (посмотрите на 2 строки с комментарием <--- Problem line
). В режиме отладки местоположение этой строки не имеет значения, и оно работает в любом месте.
Мой вопрос в том, что это исправить, и почему это проблема для начала? Спасибо и дайте мне знать, если я могу сделать вопрос более ясным.
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;
}
Посмотрите на область вашей переменной, которую вы ** адресуете ** ('& dispidNamed') внутри разбитого блока (подчеркивайте * внутри *). За пределами этого блока * он больше не существует *. Таким образом, вы отправляете 'dispParams' на вызов API, хорошо загруженный оборванным указателем. – WhozCraig
О, ничего себе, это довольно очевидно ... как обычно, огромная трата времени на что-то немое. – donkrx
Верные слова о том, что никогда не говорили о жизни инженера-программиста. Удачи. – WhozCraig