WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: jwteunisse on March 19, 2016, 04:03:40 AM

Title: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 19, 2016, 04:03:40 AM
In January, 22nd I posted a question in the Subject Script Exchange/Code samples with the title: 'Winbatch script sending and receiving MQTT messages'.
Until now I did not receive any remarks or suggestions, so I decided to develop a sample DLL in C using Code::Blocks/MinGW as IDE.

The C DLL is based on the Eclipse paho-mqtt C DLL's and a C sample program.
The C sample program I transformed in the mqttPubMsg DLL to be called from a Winbatch script.
The C sample program connects to the MQTT broker (mosquitto) on a Windows10 'server', and publish a message (payload) on a certain topic.

The mqttPubMsg.dll calls the paho-mqtt3c.dll to handle the connection to the broker and to publish the payload message.
As a first step I developed a skeleton DLL in order to test if the DLLCall in the Winbatch script works ok and a result is given back to the WB script.
This first step worked fine. The second step was to assign various C variables with the relevant values based on the paho-mqtt3c.dll function parameters.
Also this version of the dll worked fine.
As the 3rd step I started to call the first paho-mqtt3c.dll function in order to create the connection to the MQTT broker.

Calling this version of the mqttPubMsg.dll in the WB script gives an error 'DLL not loaded'.
While using a C test program works ok, and also the call to a VBA script works correctly.
In both use cases the messages are received by the broker and published to a test subscriber program.

Both DLL's and the paho-mqtt3c.lib are stored in the same Windows directory as the WB script.
My Winbatch version is 2015B running Windows 10 Pro (64bits)

After searching the Tech KB & WB forum and other internet forums for several hours I'm stuck. The mqttPubMsg.dll works fine using a VBA script and a C program, but not in WB.
What can be the cause of the problem and what can be the solution?
In the attached ZIP file are the 3 sources (WB, VBA, C) and the source code of the mqttPubMsg.dll.

Many thanks in advance, best regards, Jan Willem Teunisse   
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: JTaylor on March 19, 2016, 05:32:19 AM
Is the DLL configured to use IDispatch?  That is required for WinBatch.

Jim
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 19, 2016, 05:50:57 AM
This term iDispatch is new to me, so the answer to your question is probably no.
Where can I find this information how to use iDispatch, because I did read not this in the tutorials about using your own DLL's.

regards
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: JTaylor on March 19, 2016, 06:47:41 AM
Was thinking that was configured in the compiler but not seeing it in Visual C++.   Maybe I saw it in Visual C#.    I'll shut up and let someone who knows what they are talking about respond.

Jim
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 19, 2016, 08:50:37 AM
No need to worry about COM interfaces like IDispatch since you are not using COM but assuming you are not using a language file, WinBatch does not have an error message that includes the text "DLL not loaded".  So the question becomes where exactly in your script are you seeing this error message? Or do you mean error 1300, "Dll: File not loadable".  If it is the latter, there are numerous possibilities .  For example, compiling the dll as 64-bit and trying to load it into 32-bit WinBatch or visa versa.   Since you know your compiler and linker settings,  only you can figure out what the cause might be.
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 19, 2016, 09:21:02 AM
I'm sorry: the error message is indeed 1300 DLL file not loadable.

The error occurs in the statement
ScriptDir = DirScript()
DLL_Path = Strcat(ScriptDir, "mqttPubMsg.dll")
if FileExist(DLL_Path) then
   dllhandle=DllLoad(DLL_Path)   ;; here error occurs

I also tried mqtt_version = DllCall(DLL_Path, long:"getVersion"), resulting in the same error.

The DLL is compiled with MinGW using compile options 1999 ISO C language standard and Target x86 32 bits.
The linker library setting is pointing to pah-mqttx3.lib.
I'm running 32 bits Winbatch.

Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: JTaylor on March 19, 2016, 11:33:13 AM
Sorry.  I almost always use COM interfaces and assumed that was what you were doing.

Jim
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 19, 2016, 10:53:43 PM
Quote from: jwteunisse on March 19, 2016, 09:21:02 AM
I'm sorry: the error message is indeed 1300 DLL file not loadable.

The error occurs in the statement
ScriptDir = DirScript()
DLL_Path = Strcat(ScriptDir, "mqttPubMsg.dll")
if FileExist(DLL_Path) then
   dllhandle=DllLoad(DLL_Path)   ;; here error occurs

I also tried mqtt_version = DllCall(DLL_Path, long:"getVersion"), resulting in the same error.

The DLL is compiled with MinGW using compile options 1999 ISO C language standard and Target x86 32 bits.
The linker library setting is pointing to pah-mqttx3.lib.
I'm running 32 bits Winbatch.

All WinBatch is doing at that point in your script is calling the LoadLibrary win32 API.  You are getting the error because the OS (not WinBatch) does not believe that the file is a valid x86 Windows DLL.  WinBatch  would generate a different error, if the file could not be found or was missing a dependent DLL.  There are two possible explanations. Either the process does not have read access to the DLL or some wrong compiler or linker setting is causing Windows to detect an invalid DLL.   
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 20, 2016, 03:53:48 AM
Thanks for your reply. I have checked the read/execute permissions of both DLL's. I also checked again the compiler/linker settings.
As my VBA script runs succesfully with this version of the mqttPubMsg.DDL, I wonder if VBA uses the same LoadLibrary Win API as Winbatch?

Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 20, 2016, 08:39:49 AM
Again there is no mystery here.  WinBatch is calling LoadLibrary and that win32 API is not loading the file. Also, checking file permissions will not necessarily tell you whether or not a process has read access to a file.  I would recommend  writing a script that calls the LoadLibrary function directly and then using the DllLastError function to get the system error.   You can then lookup the system error to get a better idea of what the system is unhappy about.

Code (winbatch) Select
handle = DllCall('kernel32.dll', long:'LoadLibraryA', lpstr:"pathto\spiffy.dll")
if !handle
   error = DllLastError()
   Message("System Error", error)
endif
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 21, 2016, 03:28:56 PM
Some progress:
implementing your suggestion to load the library using kernel32.dll gives error 126 in Winbatch Studio as well as running the Winbatch interpreter.
Searching for loadlibrary 126 errors on the internet I remembered that the binaries for the C paho-mqttv3  are compiled/linked with VS2013. So looking up the webpage describing the Linux and Windows versions I now noticed that for Windows you need to install the VS2013 Redistributable package. After installing this packages and restarting Windows I can now say  that my WB script is now running without the 1300 error and publish nicely the MQTT payload message and topic using the WB interpreter.
But in Winbatch Studio I still get the load library 126 error.
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 22, 2016, 07:19:20 AM
You likely didn't get the CRT (or less likely some other DLL) installed in a location where ALL applications can find it.   If the CRT is the problem, the easiest fix is to statically link the CRT into your DLL.  This goes back to the point made many posts ago that the problem is likely related to compiler or linker settings...

BTW, you can us the Dependency Walker

https://technet.microsoft.com/en-us/sysinternals/bb896645 (https://technet.microsoft.com/en-us/sysinternals/bb896645)

and Process Monitor

https://technet.microsoft.com/en-us/sysinternals/bb89664 (https://technet.microsoft.com/en-us/sysinternals/bb89664)5

to ferret out missing DLLs.
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 23, 2016, 08:21:45 AM
Here is the correct URL for the Dependency Walker site:

http://www.dependencywalker.com/ (http://www.dependencywalker.com/)
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 24, 2016, 01:54:46 AM
Thanks for the tips. In my earlier internet search before posting this support question I read some tips about DepencyWalker and Process monitor.
Depency Walker: remarks were made in StackOverflow about the latest version, dated back about 10 years ago. Using it I noticed that DW found a couple of errors stating it did not find several API_WIN_CORE*.DLS, called from several MS_Win dlls.  After modifying the ENV Path setting some DLL errors were gone. But others remain, due to the fact that they are not installed on my development PC. This I have to investigate further.

ProcesMonitor: after compiling the WB script in an executable, I filtered out the tracing of the WB exe but ProcesMonitor did not log missing DLL's. The WB script was modified in calling the DLLCall statement in a 1 minute interval for a 20 minute periode and each time the MQTT payload message was delivired  to the MQTT broker and is received by the MQTT subsciber.

In The Tech Database I read a remark that Winbatch supports also .net assemblies. There is also a NuGet C# package available on Windows. I will make later today a new post with some questions on this .net subject.

Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 24, 2016, 07:21:10 AM
Can quite make out exactly what you are trying to say but  if you are still getting a 126 error n WinBatch Studio, you have one or more dlls that the process reporting the error cannot find.  And with regard to dotNet,  the Consolidated WIL Help file documents the WIL dotNet related functions and the Tech Database contains multiple examples of their use.
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 25, 2016, 03:57:56 AM
Dear TD,
What I was trying to say was the following. The remarks in Stackoverflow are related to the latest build of depencyWalker, and that is to old (29 Oct 2006 in mycase).
But I have got some more news about the 126 error in Winbatch Studio. Studying Procmon logged activitities with running my WB script in Winbatch Studio showed me that after calling my mqttPubMgs.dll in the script directory (d:\Winbatch\Ontw) Studio was trying first to find the paho-mqtt3c.dll not in my script directory but in d:\Winbatch\system and then following the directories as defined in the PATH Env variable.

I regard that as strange behavior, I'm expecting a DLL first is searched in the directory where the executable or script is being executed.

After copying the paho-mqtt3c.dll in d:\Winbatch\system no errrors where shown in the Procmon log and the WB script was also exectued with no errors.

I think I can now finish my development by calling the DLL's in my final project WB script,

With regards

Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: td on March 25, 2016, 08:37:18 AM
WinBatch Studio does search its executable's location and there is absolutely nothing 'strange' about the search sequence.  The dll search order is both well documented and well know in the Windows development community. Microsoft has a extensive article on dll search order and how it is influenced by registry settings and Windows version on their MSDN site.  The article also explains the security based reasons for that search order.  It is recommended reading.

There is a difference between WinBatch and WinBatch Studio that can affect DLL search order.  WinBatch has some legacy code in its startup routines that sets an old  hidden DOS environment variable that has the effect of making the running script's path the current working directory.  Amazingly, all versions of Windows still respect this legacy environment variable.  WinBatch Studio's debugger does not set that variable for more reasons that I care to go into here.   However, you can imitate WinBatch behavior in the debugger by placing the following at the top of your script

Code (winbatch) Select
if RtStatus() == 10 then DirChange(DirScript())


Also, I wouldn't be to concerned about the age of Dependency Walker.  The only thing to worry about is whether or not it still works and making sure you start it with the correct security token in UAC environments.
Title: Re: Call to a C DLL gives DLL not loaded, while same VBA/Excel script works fine.
Post by: jwteunisse on March 26, 2016, 04:25:44 AM
Thanks again for your explanation. I will keep it in mind for the next development project.  :)