I originally posted this as an answer to Trouble with file location in excel/fortran dll connection since the problem seems similar. But since that is an older question referencing fortran I decided to post as a new question since I think more people will have experience with this in c++ (sorry, first time posting on SO so please bear with me).
The problem arises when calling from VBA a c++ dll which references a second c++ dll. The reason I am doing this is because I am working on different dll projects which share some similar functionality, so I want to have a single utilities dll which they can all reference. My set-up is:
Visual Studio Express 2013 V12.0
Excel 2010 V14.0 (64-bit), VBA V7.0
When there is just one dll project everything works fine as usual. In its most simplified form, I have a Solution called 'a' containing a Project called 'a' containing the following two files:
// a.cpp
void __stdcall a() {}
// a.def
EXPORTS
a
I specify a.def as the Module Definition File under Linker Input in the Project Property pages and then compile to produce the a.dll file. Over in VBA I have:
Declare PtrSafe Sub a Lib "C:\ ... \a.dll" ()
Sub test()
a
End Sub
a.dll is sitting where it was created in "C:\ ... \Visual Studio 2013\Projects\a\x64\Debug\" and the test Sub enters it fine. Then I add to the Solution a second dll project called 'b' containing the following three files:
// b.h
void __stdcall b();
// b.cpp
#include "b.h"
void __stdcall b() {}
// b.def
EXPORTS
b
I change the a.cpp definition to:
// a.cpp
#include "b.h"
void __stdcall a() {
b();
}
In the 'a' Project properties I specify the path to b.h under Additional Include Directories and I add a Reference to b under Common Properties. Everything compiles fine. Back in VBA I add:
Declare PtrSafe Sub b Lib "C:\ ... \b.dll" ()
Sub test1()
a
b
End Sub
test1 produces the run-time error '53': File not found "C:\ ... \a.dll" despite the fact that I can see it sitting there in the same location it was before. Bizarrely though, if I change the calling order of a and b in the sub then it does work:
Sub test2()
b
a
End Sub
So VBA can find b and somehow it seems that's enough to prompt it to find a again.
Anyway, the solution was to place copies of a.dll and b.dll in the Excel/VBA current working directory CurDir(). Strangely, I did not actually have to change the Lib path in the Declare statement to the CurDir (although I could). And I can tell it is really the dlls in the original VS folder which are running because if I make detectable changes to a.cpp and b.cpp and recompile without re-copying the new dlls to the CurDir, VBA definitely runs the new dlls in the VS folder not the old copies in the CurDir. Somehow the mere presence of the copies in the CurDir is enough to prompt VBA to find the specified dlls in the VS folder. Maybe someone else can throw some light on this behavior ...
Although mystifying to me, it was not inconvenient since I am developing the dlls and did not have to keep copying them after every compilation. Another solution was to save the Excel Workbook in the VS folder where the output dlls are so that the CurDir automatically contains them. Everything above holds whether VS complied in Debug or Release mode. I got help from http://communities.bentley.com/products/microstation/f/273/t/12979.aspx, however I would like to understand this seemingly inconsistent behaviour rather than just have a workaround. Thanks