Ошибка проверки времени выполнения # 0 - значение ESP не было сохранено должным образом - PullRequest
1 голос
/ 22 декабря 2011

Я пытаюсь скомпилировать пример доступа к автоматизации Excel из кода C ++ и получаю следующую ошибку: «Ошибка проверки времени выполнения # 0 - значение ESP не было должным образом сохранено при вызове функции. Обычно это результат вызова функции, объявленной с одним соглашением о вызовах с указателем функции, объявленным с другим соглашением о вызовах. "

Я уже нашел и прочитал тонны информации об этой ошибке в Интернете, но все еще не могу понять, что именно я должен исправить в своем коде, чтобы она работала. Пожалуйста, просмотрите код:

#include <windows.h>
#include <oleacc.h>
#import "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE14\MSO.DLL" no_implementation rename("RGB", "ExclRGB") rename("DocumentProperties", "ExclDocumentProperties") rename("SearchPath", "ExclSearchPath")
#import "C:\Program Files (x86)\Common Files\microsoft shared\VBA\VBA6\VBE6EXT.OLB" no_implementation
#import "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE" rename("DialogBox", "ExclDialogBox") rename("RGB", "ExclRGB") rename("CopyFile", "ExclCopyFile") rename("ReplaceText", "ExclReplaceText")

BOOL EnumChildProc(HWND hwnd, LPARAM)
{
   WCHAR szClassName[64];
   if(GetClassNameW(hwnd, szClassName, 64))
   {
      if(_wcsicmp(szClassName, L"EXCEL7") == 0)
      {
         //Get AccessibleObject
         Excel::Window* pWindow = NULL;
         HRESULT hr = AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM, __uuidof(Excel::Window), (void**)&pWindow);
         if(hr == S_OK)
         {
            //Excel object is now in pWindow pointer, from this you can obtain the document or application
            Excel::_Application* pApp = NULL;
            pApp = pWindow->GetApplication();
            pWindow->Release();
         }
         return false;     // Stops enumerating through children
      }
   }
   return true;
}

int main( int argc, CHAR* argv[])
{
    //The main window in Microsoft Excel has a class name of XLMAIN
    HWND excelWindow = FindWindow(L"XLMAIN", NULL);
    //Use the EnumChildWindows function to iterate through all child windows until we find _WwG
    EnumChildWindows(excelWindow, (WNDENUMPROC) EnumChildProc, (LPARAM)1);
    return 0;
}

Ответы [ 2 ]

6 голосов
/ 22 декабря 2011
EnumChildWindows(..., (WNDENUMPROC) EnumChildProc, ...);

Это (WNDENUMPROC) приведение только остановило компилятор от сообщения, что вы делали это неправильно.Это не помешало вам сделать это неправильно.Исправление:

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM)
{
    // etc..
}

Обратите внимание на добавленный макрос CALLBACK, он выбирает требуемое соглашение о вызовах __stdcall для обратного вызова.Без него по умолчанию используется __cdecl, еще одно соглашение о вызовах, которое требует от вызывающей стороны очистить стек после вызова.Что не произойдет, и, таким образом, дисбаланс в стеке.

Надлежащая сигнатура обратного вызова задокументирована здесь .

4 голосов
/ 22 декабря 2011
BOOL EnumChildProc(HWND hwnd, LPARAM)

Должно быть:

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM)
...