运行时检查失败 #0 - 未正确保存 ESP 的值

Run-Time Check Failure #0 - The value of ESP was not properly saved

本文关键字:确保 保存 ESP 的值 检查 失败 运行时      更新时间:2023-10-16

我正在尝试从C++代码编译Excel自动化访问的示例,但出现以下错误:"运行时检查失败#0 - ESP的值未在函数调用中正确保存。 这通常是调用使用一个调用约定声明的函数的结果,该函数指针声明了不同的调用约定。

我已经在互联网上找到并阅读了有关此错误的大量信息,但仍然无法理解我应该在我的代码中修复什么才能使其工作。请查看代码:

#include <windows.h>
#include <oleacc.h>
#import "C:Program Files (x86)Common Filesmicrosoft sharedOFFICE14MSO.DLL" no_implementation rename("RGB", "ExclRGB") rename("DocumentProperties", "ExclDocumentProperties") rename("SearchPath", "ExclSearchPath")
#import "C:Program Files (x86)Common Filesmicrosoft sharedVBAVBA6VBE6EXT.OLB" no_implementation
#import "C:Program Files (x86)Microsoft OfficeOffice14EXCEL.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;
}
EnumChildWindows(..., (WNDENUMPROC) EnumChildProc, ...);

那个(WNDENUMPROC(强制转换只是阻止编译器告诉你你做错了。 它并没有阻止你做错事。 修复:

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

请注意添加的 CALLBACK 宏,它为回调选择所需的__stdcall调用约定。 如果没有它,它将默认为 __cdecl,这是另一个调用约定,要求调用方在调用后清理堆栈。 这不会发生,从而不平衡堆栈。

此处记录了正确的回调签名。

BOOL EnumChildProc(HWND hwnd, LPARAM)

需要:

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM)