Location of custom DLL for use with MSAccess

B

Bob Hairgrove

I have developed a DLL in C++ for use with an Access 97 database
application. The OS it will run on is Windows 2000 Professional (my
development environment) and Windows XP (my client has this).

Usually, I only do this sort of thing when I need to call some Windows
API functions. Those DLLs are always in the Windows system32
directory. ActiveX DLLs are registered in the Windows registry, so
Access can find those. This time, however, there is no COM involved;
all the exported functions are declared extern "C" __stdcall, and the
function names are exported undecorated by using a DEF file when
building the DLL.

All is well when the DLL is either in the Windows system32 directory
or in the directory where MSAccess.exe is; if I put it in the folder
containing the MDB file, Access cannot find the DLL. Obviously, it's
not a good idea to hard-core the file path in the class module's
"Private Declare Function ... Lib "MyDLL.dll" (etc.) because the
client might not have the same folder. Putting it in the user's
Application Data folder doesn't work, either (at least not on Windows
2K using MSAccess 97). And I'd rather not put it in the system32
directory because it is easily forgotten there, and it might get in
the way when an update is due.

What is the usual way out of this mess? Is there some documented (or
undocumented) way of adding directories to search when Access loads
the DLL?

Thank you.
 
D

Douglas J. Steele

I believe (but can't test at the moment) that if you put them in the same
folder as the MDB, they should be found.

--
Doug Steele, Microsoft Access MVP

(no private e-mails, please)


I have developed a DLL in C++ for use with an Access 97 database
application. The OS it will run on is Windows 2000 Professional (my
development environment) and Windows XP (my client has this).

Usually, I only do this sort of thing when I need to call some Windows
API functions. Those DLLs are always in the Windows system32
directory. ActiveX DLLs are registered in the Windows registry, so
Access can find those. This time, however, there is no COM involved;
all the exported functions are declared extern "C" __stdcall, and the
function names are exported undecorated by using a DEF file when
building the DLL.

All is well when the DLL is either in the Windows system32 directory
or in the directory where MSAccess.exe is; if I put it in the folder
containing the MDB file, Access cannot find the DLL. Obviously, it's
not a good idea to hard-core the file path in the class module's
"Private Declare Function ... Lib "MyDLL.dll" (etc.) because the
client might not have the same folder. Putting it in the user's
Application Data folder doesn't work, either (at least not on Windows
2K using MSAccess 97). And I'd rather not put it in the system32
directory because it is easily forgotten there, and it might get in
the way when an update is due.

What is the usual way out of this mess? Is there some documented (or
undocumented) way of adding directories to search when Access loads
the DLL?

Thank you.
 
S

Stephen Lebans

Hi Doug,
it has to be in the same folder as the FE of your app. Also, you can place
it on a network share but I find you have to then hard code the path to the
function declarations. I'm not sure why the OP states that placing the DLL
in the same folder as his app causes a failure.

The rules for Windows to search/find DLL's are clearly stated on the MSDN
site. I think the starting point is LoadLibrary. The OP could use
Loadlibrary to force the loading of his DLL from a specified location
determined at runtime.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/loadlibrary.asp

--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
 
B

Bob Hairgrove

Hi Doug,
it has to be in the same folder as the FE of your app. Also, you can place
it on a network share but I find you have to then hard code the path to the
function declarations. I'm not sure why the OP states that placing the DLL
in the same folder as his app causes a failure.

Maybe because later versions of Access search the MDB's folder?
Apparently, Access 97 des not.
The rules for Windows to search/find DLL's are clearly stated on the MSDN
site. I think the starting point is LoadLibrary. The OP could use
Loadlibrary to force the loading of his DLL from a specified location
determined at runtime.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/loadlibrary.asp

Many thanks to you and Douglas for your replies. Remember that this is
Access 97 ... I get an error 53 "file not found" when the DLL is in
the same folder as the front end MDB file. When it is in the Office
folder (i.e. where MSACCESS.EXE is), there is no error. This is also
more or less what is expected according to the documentation, because
an MDB is not the "application" as far as Windows is concerned --
MSACCESS.EXE is the application.

But I believe that LoadLibrary will do what I need. All the functions
in the DLL are wrapped in a class module, and Access doesn't load the
DLL until I use the class module. I am fairly certain that Access uses
LoadLibrary (or LoadLibraryEx) internally to load the DLL (how
else??), and the docs say that if I have already loaded the DLL,
subsequent calls to LoadLibrary will return the handle to the one
already mapped into the process memory. So I just have to call
LoadLibrary once with the full path for which I can let the user
browse.

Time to do some tests! Thanks again,
 
R

Rick Brandt

Bob said:
Maybe because later versions of Access search the MDB's folder?
Apparently, Access 97 des not.

I use Stepen's Mousehook.dll with Access 97 just by placing it in the app folder
and it works fine.
 
B

Bob Hairgrove

I use Stepen's Mousehook.dll with Access 97 just by placing it in the app folder
and it works fine.

If you all say that it works, I believe you! It just doesn't work for
me. I also added the path to my MDB file to my system's PATH
environment variable ... still no cigar, although the MSDN docs say
that the directories listed in the PATH variable are also searched. I
guess it's just "one of those things" that enhance my love/hate
relationship with the beast MSAccess. :)

In the meantime, I was able to get it to work by calling LoadLibrary
before using the class library (and calling FreeLibrary afterwards to
ensure that the DLL's reference count is properly decremented).

There is a new API function in Windows XP called "SetDllDirectory";
unfortunately, this doesn't exist on Windows 2000.

In case you are interested, I am using a German version of Access 97
with SP2 installed, running on an English-language version of Windows
2000 with SP4 installed. The internationalization of Access shouldn't
come close to touching any of the code used to implement the loading
of DLLs, though.
 
B

Bob Hairgrove

The rules for Windows to search/find DLL's are clearly stated on the MSDN
site. I think the starting point is LoadLibrary. The OP could use
Loadlibrary to force the loading of his DLL from a specified location
determined at runtime.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/loadlibrary.asp

Thanks, Stephen ... LoadLibrary made it work! :)

[If you do this at home, don't forget to save the module handle
returned by LoadLibrary and use that as the argument to call
FreeLibrary after you are done with the DLL ... otherwise, the usage
reference count might not be decremented properly...]
 
A

Albert D. Kallal

I use Stepen's Mousehook.dll with Access 97 just by placing it in the app
folder and it works fine.

Actually, that works because the wonderful Stephan uses some code (load
library api) to load in the dll.

This also why Stephens pdf makers also works. You just throw in the dll into
the *same* directory as the mdb/mde file (but, Stephans code actually grabs
the current mdb/mde dir, and then LOADS the dll via an api call... that is
why it works!!!).

So, to the original poster, yes...your solution is to use the load library
api (as Stephan does)

eg:

Private Declare Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long

Private Declare Function FreeLibrary Lib "kernel32" _
(ByVal hLibModule As Long) As Long


Now, in your code, just go:
dim lngHandle as long

lngHandle = LoadLibrary(CurrentProject.Path & "\zip32.dll")

You library is now loaded, and you don't have to register it.
(currentProject.Path returns the path of the current location of the mdb/mde
running).
So, using loadlibary means you don't have to place the dll in the
msaccess.exe, or system32 dir, but simply "place" the dll in the same dir as
the mdb, and use the above loadLibary. I learned this trick from
Stephan...and...wow, what a great find!!!

Download Stephens PDF maker for a good example of loading a dll in the same
directory as the mdb file. The above loadlibary line of code will
essentially do what you want. Stephens pdf example also does this, and can
be found here:

http://www.lebans.com/reporttopdf.htm

My WinZip library for ms-access also does this, and can be found here:

http://www.members.shaw.ca/AlbertKallal/zip/index.htm

The above example means you place the two zip dll's in the same directory as
your mdb/mde, and you have full WinZip abilities built into your
application!!!
 
S

Stephen Lebans

I'm getting old Albert. I completely forgot that I was using LoadLibrary to
load the DLL from the current folder.
;-(
--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
 
B

Bob Hairgrove

Actually, that works because the wonderful Stephan uses some code (load
library api) to load in the dll.

[snip]

Thank you, Albert, for saving my sanity! :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top