Excel cannot find DLL - excel

I have an excel VBA macro that calls a function in a C++ DLL.
The declaration is
Public Declare PtrSafe Function XXXX Lib "xxxx.dll" (...
This has worked for years, but on some new computers, it fails with the message
“xxxx.dll not found”.
The DLL is in the current folder. I checked with CurDir() and the current folder is correct.
I have a C++ test program that calls the DLL and it succeeds so there are no missing dependencies.
If I add the folder to the PATH environment variable, it will succeed.
According to all the documentation I found, Excel will always look in the current folder for DLLs.
Any ideas would be appreciated.
Thank you.

Related

VBA: how to set a dynamic library path for declare statement?

I have a program in Excel's VBA that need to call some methods from a DLL, both are under my control in term of code development. I need to be able to select what DLL library (from various releases) should be used at runtime, but the Declare statement from VBA only allow for constants in the Lib path.
The objective is multiple :
Be able to select the library release at runtime from one Excel workbook
Ease the code maintenance because a lot of library methods are used, meaning a lot of Declare statement to be edited when library path is changed
Search dynamically at runtime the library from various predefined locations, to comply with deployment purposes. In dev environment, the library is in a dev directory, but for end-users, the library could be in 3 various locations: the workbook path, a specific directory on the computer, or a specific directory from a network drive.
I tried to declare the path in Public Const variable, but it doesn't works:
' This work
Private Declare PtrSafe Function addAmplifier Lib "path\to\lib.dll" (...) As Integer
' This don't work
Public Const libPath As String = "path\to\lib.dll"
Private Declare PtrSafe Function addAmplifier Lib libPath (...) As Integer
Is there a hijack way to use a variable in the Declare statement ? Or is there a way to create a VBA module able to edit the VBA code of the second module where the Declare statements are located in, and replace with regexp all occurrences of a String, save the VBA project then execute the module ? More formally : can VBA code rewrite itself at runtime ?
As suggested by L8n, the solution to change the working directory works fine.
So if the libraries are located in a sub-folder into the workbook path, we can do the following process each time a DLL native function is called :
Change the working directory to go into the sub-folder with ChDir()
Execute the native function
Go back to the parent folder with ChDir()
However, I suspect the Frequent call of ChDir() could slow down the VBA execution since it also seems to update the execution context with some hidden variables from the VBA runtime.

Excel 2016 VBA failed calling vs2015 c++ dll

Recently upgraded to a new PC with Win 10 pro, Excel 2016 coming with Office365, vs2015 community. Built a very simple vc++ dll with just one function exported in def file. The code is very simple but would still post here to give a content and make sure there's no problem there.
//also tried __declspec(dllexport) double sumCPP(double a, double b) without .def file
double __stdcall sumCPP(double a, double b)
{
return a + b;
}
'VBA
Public Declare PtrSafe Function sumCpp Lib "C:\MyTestProject\x64\Debug\DllTest.dll" (ByVal a As Double, ByVal b As Double) As Double
But a call from VBA results Run-time error '48': File not found: C:\MyTestProject\x64\Debug\DllTest.dll.
The source code of a more complicated dll project can be built to exe that runs fine, but whose dll prompted this original failure calling dll problem. Any suggestion where to look at? I've tried depends.exe with many supposedly false alarms and dumpbin /dependents but not clear how to use the result. I wonder if this is related to some vs2015 redistributable not in system PATH. I don't see any there but haven't tried to add them yet, as there seem to be too many.
Is there any other option to delegate heavy computation and TCP/IP socket besides using vc++ dll? I don't know but can consider C#, while python would be preferred. Since those dll functions are intended to be called many times in VBA, a system call to vc++ exe doesn't seem to be efficient.
Great thanks in advance!
Since the machine is new so I reset it removing all data. Then I installed Office 2016 64bit and VS Community 2015 from scratch and built the 64bit dll again. This time the error is Run-time error '453' Can't find DLL entry point. Can't find any obvious missing dependent dll by either dumpbin.exe /dependents or depends.exe.
Try change build configuration from "Debug" to "Release"

Visual Studio 2008 c++ linker refuses to link?

I am banging my head against a wall here.
All i want is to link a static .lib file in a cpp windows forms application! So, i have an include folder in my project folder that holds header files for that .lib (lib is Yaml-cpp if someone wonders). And i have a lib folder that has the .lib files for that library.
I tested it on a blank project
1.I make a new windows forms project in VS2008, in C++.
2.I go to project properties - c/c++ general and additional include directories that have yaml-cpp header files
3.I go to linker and add path to my lib directory
4.I go to linker - input and add my .lib file
5.I check linker command line and it contains my .lib file so it must be all set.
6.Then i write the sample code in an onbutton function body (which appears in form1.h fie).
Sample code is from here http://code.google.com/p/yaml-cpp/wiki/HowToParseADocument and its just as simple as:
#include <fstream>
#include "yaml.h"
and then:
std::ifstream fin("test.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
while(parser.GetNextDocument(doc)) {
//do nothing yet
}
7.And then i compile and have 10 "unresolved externals".
I have looked into another project that uses same library, and it has exactly same directory structure, same name of .lib added in linker - input - additional dependencies, same .lib and .h files. And it works for that project- but it doesnt work for me.
What in the world is wrong?
EDIT: I tried making new windows 32 console application and it worked correctly. I then tried to make another fresh windows forms application and it failed.
It is confirmed now. Same steps for linking a library work in console application and fail in windows forms application. WHY?
What you've done seems correct from your explanation, let's do some blind troubleshooting.
Try giving full path instead of relative path for library path and additional include directories. (but as u said that the file is getting read, that should be the problem.)
If you are using a copy of original libyaml-cppmdd.lib and its include file, check whether the header file that gets included is of the same version as the lib.
Check whether there are any functions in any part of the code that is having a declaration but no definition.
Check whether you're accessing any private functions from the library.
Please read this Microsoft article on Troubleshooting UnResolved External Symbol error.
Hope it helps!

How to modyfy resource in a DLL from this DLL?

I'm writing an add-on for IE using VC++ and ATL.
It's a simple DLL and I have a text file that I use as a resource. This answer helped me in doing this.
I have a question about updating resource. MSDN describes how to do it but there is a function (BeginUpdateResource) that need filename of exe or dll with resource.
Is it possible to update resource in my DLL from my DLL? I can easily read it that way, but to update I have to provide DLL's name. Is it necessary?
Also if I won't give full path to my DLL it looks for file on desktop and not where DLL is stored. I don't know why this behave like this.
I have never tried to do this so I might be wrong, but I would be surprised if a DLL could update its own resources. If the DLL file is loaded then I would expect the file containing the DLL to be locked for reading and for write attempts to that file to fail.
Still, if you want to try, just have the DLL pass its own path to the function.
You can get your DLL's path using GetModuleFileName by passing your DLL's HINSTANCE / HMODULE (they are the same thing these days) as the first argument. The HINSTNACE / HMODULE is passed to you in DllMain.

.h, .dll and .lib confusion

I'm new to vc++. I've just built a software and it generated a .dll and a .lib. I need to use functions from this in my code. Do I need to link to both .lib and .dll to build my code? What project properties do I have to alter to do this linking?
Actually, you need only the .dll file. It contains all the necessary code and data to run it's functions. It also contains a table that links the symbolic names of the functions (e.g. the function PrintMe), their ordinals (the number of that function in the DLL) and their addresses in the DLL.
If you want to use only the DLL, you have to "manually" get the symbols resolved:
Let's say you want to use the function PrintMe of the DLL. What you had to do is to resolve it's name (PrintMe) or it's ordinal (PrintMe is the 1st function of the DLL) to it's address. For this, you could use LoadLibrary, GetModuleHandle and GetProcAdress from the Win32 API (aka Windows SDK). Additionally, this method allows you to load the DLL at runtime (see below).
The easier way is to use the MSVC(++) features __declspec(dllexport) and __declspec(dllimport), e.g.
// your DLL
__declspec(dllexport) void PrintMe()
{
printf("Hello World!");
}
// you project to use the DLL
__declspec(dllimport) void PrintMe();
The first one (dllexport) tells the compiler to export the function. The second one (dllimport) is the interesting one: It creates all the necessary code to be able to use the function from the DLL.
For this, you need the .lib file in your project (which wants to use the DLL). The .lib file contains information for the linker to resolve the symbol name (PrintMe) to its address in the DLL. Since the .lib is statically bound, the linker can make use of it - the DLL on the contrary is bound at runtime / loading time, so the linker cannot use it. (Yes, the information in the .lib file is redundant.). Note: You cannot change the whole DLL when using this method w/o rebuilding your project with the new .lib file. Some structure changes affect the addresses of the functions in the DLL, see this SO answer.
One last difference between using the Win32 API (LoadLibrary...) and the MSVC method via __declspec is the loading of the DLL. When you use LoadLibrary, the DLL is loaded at runtime, of course (so you can catch exceptions when it cannot be found and so on). The other method loads the DLL at loading time, so you program will terminate (will not run) when Windows cannot find the DLL.
When you create a project in VS, you can activate the "export symbols" checkbox at the end of a wizard (Win32 project). That gives you some examples of exported symbols. Additionally, it introduces a macro plus a preprocessor defition plus some directives that are very useful:
// DLL header
#ifdef _YOUR_DLL_EXPORTS
#define YOUR_DLL_API __declspec(dllexport)
#else
#define YOUR_DLL_API __declspec(dllimport)
#endif
YOUR_DLL_API PrintMe();
You now can use this header file to build you DLL as your DLL project has that _YOUR_DLL_EXPORTS definition (see project properties page, C++, preprocessor). The project that uses the DLL can use this header, too, but then must not have such a name defined. When you include the header file in the project in which you want to use the DLL, the macro is resolved to __declspec(dllimport). This instructs the linker to look for this function (which is found in the .lib file) and create all the necessary code to load the DLL at runtime and resolve the symbol name.

Resources