none
Debugging a C++ DLL from VBA

    Question

  • I wrote a DLL with C++.

    I have an Excel/VBA program that calls a function in that DLL.

    When I debug my VBA program, I'd like to be able to step into the DLL function call.

    In other words, if I'm stepping through the VBA program using the VBA IDE in Excel, I'd like to be able to step into a DLL function and start debugging the C++, line by line, in a previously opened Visual Studio window.

    Is this sort of thing possible?

    Thanks!
    Pete
    Wednesday, November 07, 2007 5:58 AM

Answers

  • Here's the answer(s).

    I managed to figure out a way of doing it.   Include assert.h and place an assertion at the top of your function call.  Like this:

    Code Block

    #include "stdafx.h"
    #include <assert.h>

    BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
    {
        return TRUE;
    }


    long __stdcall sumLongs2D( long *arrayOfLongs, long N1, long N2 )
    {
        assert( false );

        long sum = 0;

        for (int i=0; i < N1; i++)
            for (int j=0; j < N2; j++)
                sum += *(arrayOfLongs + i*sizeof(long) + j);

         return sum;
    }


    You can leave Visual Studio running if you like.

    Next run Excel and load the spreadsheet that contains the VBA function that calls this function.   Run the function.   The assert will cause a SIGABRT to be raised.   You have a few dialogs to click through, which should be fairly obvious to navigate ("Do you want to debug the program?").  You'll be dumped into the code for assert().    Click "step out" to leave the stack frame for assert() and you're dumped into your DLL function and can perform debugging to your heart's content.

    You can write a little macro function that gets defined whenever you set /D DEBUGDLL so that the assert is called only when you want to debug the DLL but gets left out of the code otherwise.   With the code snippet below, you'd replace the call to assert() with BREAK_IF_DEBUG.

    Code Block

    #pragma once

    #ifdef DEBUGDLL
    #include <assert.h>

    #define BREAK_IF_DEBUG assert(false);
    #else
    #define BREAK_IF_DEBUG
    #endif






    It's a total hack, and aesthetically ugly, but convenient.    This method is the "real" method, is more elegant but a little less convenient.

    1. Set: Project Properties | Debugging | Command = C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE
    2. Make sure you're using the debug configuration so that the symbol table is generated.
    3. Set Project Properties | C/C++ | Browse Information | Enable Browse Info = Include All Browse Information (/FR)
    4. Put your cursor somewhere in the C++ DLL function that you want to debug.   Set a breakpoint somewhere.
    5. Run it (F5).   Excel will run.
    6. From Excel, load the spreadsheet that contains the VBA function that calls your C++ DLL function.
    7. Run the VBA function that calls the C++ DLL function.

    You'll be debugging the C++ DLL.   This method is a little less convenient than my method because eveytime you want to debug the DLL, Excel will run and you need to reload your spreadsheet, view the VBA code editor, navigate to your function, and run the VBA function.   In my method, the VBA code window stays open always.

    So there you go.  Two ways to debug the C++ code in a DLL that's called by VBA.   Hope this is useful.

    Pete



    Wednesday, November 07, 2007 10:49 PM

All replies

  • Yes, you can very well debug the C++ DLL from VBA.

     

    Put a break point in C++ DLL function and debug the VBA code.

     

    Regards,

    Paresh.

     

    Wednesday, November 07, 2007 6:22 AM
  • The VBA IDE does not support stepping into the DLL code. You can use the VC debugger's "attach to process"  feature to attach to Excel.exe or use the Visual Studio Tools for Office which provides you with a much more advanced debugging functionality than can be found in the VBA IDE.

    Wednesday, November 07, 2007 7:00 AM
  • I am not sure of the details, but I think you can execute Excel using the debugger and then you can debug your program when it executes. The debugger will complain that not everything has been built with debugging information but if your program is built as a debug build then that should be all you need.

     

    If you want to use the attach to process technique, then IsDebuggerPresent() might help.To attach, you will need to have the opportunity to attach while your program is executing, and you can use IsDebuggerPresent() in your program to know when you need to do something to cause the program to wait and give you a chance to attach.

     

    The documentation probably has more suggestions that could help.

    Wednesday, November 07, 2007 7:55 AM
  • Here's the answer(s).

    I managed to figure out a way of doing it.   Include assert.h and place an assertion at the top of your function call.  Like this:

    Code Block

    #include "stdafx.h"
    #include <assert.h>

    BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
    {
        return TRUE;
    }


    long __stdcall sumLongs2D( long *arrayOfLongs, long N1, long N2 )
    {
        assert( false );

        long sum = 0;

        for (int i=0; i < N1; i++)
            for (int j=0; j < N2; j++)
                sum += *(arrayOfLongs + i*sizeof(long) + j);

         return sum;
    }


    You can leave Visual Studio running if you like.

    Next run Excel and load the spreadsheet that contains the VBA function that calls this function.   Run the function.   The assert will cause a SIGABRT to be raised.   You have a few dialogs to click through, which should be fairly obvious to navigate ("Do you want to debug the program?").  You'll be dumped into the code for assert().    Click "step out" to leave the stack frame for assert() and you're dumped into your DLL function and can perform debugging to your heart's content.

    You can write a little macro function that gets defined whenever you set /D DEBUGDLL so that the assert is called only when you want to debug the DLL but gets left out of the code otherwise.   With the code snippet below, you'd replace the call to assert() with BREAK_IF_DEBUG.

    Code Block

    #pragma once

    #ifdef DEBUGDLL
    #include <assert.h>

    #define BREAK_IF_DEBUG assert(false);
    #else
    #define BREAK_IF_DEBUG
    #endif






    It's a total hack, and aesthetically ugly, but convenient.    This method is the "real" method, is more elegant but a little less convenient.

    1. Set: Project Properties | Debugging | Command = C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE
    2. Make sure you're using the debug configuration so that the symbol table is generated.
    3. Set Project Properties | C/C++ | Browse Information | Enable Browse Info = Include All Browse Information (/FR)
    4. Put your cursor somewhere in the C++ DLL function that you want to debug.   Set a breakpoint somewhere.
    5. Run it (F5).   Excel will run.
    6. From Excel, load the spreadsheet that contains the VBA function that calls your C++ DLL function.
    7. Run the VBA function that calls the C++ DLL function.

    You'll be debugging the C++ DLL.   This method is a little less convenient than my method because eveytime you want to debug the DLL, Excel will run and you need to reload your spreadsheet, view the VBA code editor, navigate to your function, and run the VBA function.   In my method, the VBA code window stays open always.

    So there you go.  Two ways to debug the C++ code in a DLL that's called by VBA.   Hope this is useful.

    Pete



    Wednesday, November 07, 2007 10:49 PM
  •  Sara Sings wrote:
    The assert will cause a SIGABRT to be raised.   You have a few dialogs to click through,

    Another possibility is to use a MessageBox, and when you get the message, attach to the process as previously suggested. I think once you have attached, you can continue to debug without attaching again.

     

     Sara Sings wrote:

    1. Set: Project Properties | Debugging | Command = C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE

    Which is what I suggested.

     Sara Sings wrote:

    You'll be debugging the C++ DLL.   This method is a little less convenient than my method because eveytime you want to debug the DLL, Excel will run and you need to reload your spreadsheet, view the VBA code editor, navigate to your function, and run the VBA function.   In my method, the VBA code window stays open always.

    I am not sure, but there is probably a way you can stay within Excel and also modify and debug the program repetively.

     

    Perhaps you could execute Visual Studio from within Excel to establish a debugging session.

    Thursday, November 08, 2007 12:49 AM