【问题标题】:Run-Time Check Failure #0 - The value of ESP was not properly saved运行时检查失败 #0 - ESP 的值未正确保存
【发布时间】:2012-01-25 15:23:12
【问题描述】:

我正在尝试从 C++ 代码编译 Excel 自动化访问示例,但出现以下错误:“运行时检查失败 #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;
}

【问题讨论】:

  • 很明显,MS Visual Studio 使用 __cdecl 调用约定,而 EnumChildWindows() 使用 __stdcall。这种不匹配会导致错误。问题是应该在代码或 IDE 中进行哪些更改以消除此错误?
  • 无需更改任何内容。只需按照in the documentation 的描述将 CALLBACK 宏添加到您的函数定义中,您就可以开始了。该宏为您设置了正确的调用约定,因此您无需担心它实际上是什么。

标签: c++ excel automation runtime runtime-error


【解决方案1】:
BOOL EnumChildProc(HWND hwnd, LPARAM)

需要:

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM)

【讨论】:

    【解决方案2】:
    EnumChildWindows(..., (WNDENUMPROC) EnumChildProc, ...);
    

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

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

    注意添加的 CALLBACK 宏,它为回调选择所需的 __stdcall 调用约定。没有它,它默认为 __cdecl,这是另一个要求调用者在调用后清理堆栈的调用约定。这不会发生,因此会导致堆栈不平衡。

    正确的回调签名是documented here

    【讨论】:

      猜你喜欢
      • 2023-03-06
      • 2012-04-22
      • 1970-01-01
      • 2011-01-26
      • 2010-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多