Collection of DLL's in another Designated Folder?
Asked Answered
M

5

5

First of all, please forgive me for not knowing the proper terminology, I'm sure there's a very common technical name for this which I could simply Google for help - but I can't find help if I don't know the term to begin with.

I'm building a modular system in Delphi 7. There are a few applications and a bunch of DLL's. All the applications share these DLL's, as well as some of the DLL's use other DLL's. The DLL's are currently saved in the same location as the application. I would instead like to put all these DLL's in a sub-folder (elsewhere from the EXE's) but of course Delphi won't know how to find them.

Is there a way I can direct my Delphi Apps to look in a certain directory for DLL's? It can't be using Contstants, because there will be an option to specify where the DLL's are stored.

These DLL's are just a plain collection of StdCall functions in each, nothing special.

EDIT:

To explain the reason why I want to keep the DLL's in their own folder: This system I'm building considers these DLL's as add-ons. By default, the system might not even have any add-ons. On the other hand, it will also allow various vendors to build other DLL's and include them as add-ons. Then each application requiring these Add-ons will be directed to the folder where to find them. The application its self will have its own DLL's which will be in the same directory as the applications. But the Vendors' DLL's I would like to keep separate.

As mentioned in the answers below, my best bet would be to implement the DLL Import method, because A) I can specify a path for each DLL it's importing, B) I can better control the use of each DLL (Does it need to be loaded or not?) and C) Each DLL can technically be in separate folders by themselves (Vendors might want to build their own folder structure). This system is still very pre-mature but I plan to make further flexibility with it.

Mapel answered 13/12, 2011 at 22:5 Comment(2)
You probably want to set the PATHBingham
@PeterTurner No, this won't help because I have many different DLL's - some may be in a different directory than others. Also, I added more to my question above to explain why.Mapel
P
4

You can do this with PATH but I recommend you don't. It's a brutal and inflexible approach. And of course you need to change the system wide PATH for it to have any effect at executable load time.

You can load your DLLs explicitly with LoadLibrary and GetProcAddress. That's no fun if there are a lot of imports but it can be a good option otherwise. And remember that if you go down this route, every single DLL must switch to explicit linking.

There is something called DLL Redirection but MS don't recommend you use that. They recommend that you use side-by-side components. Having said that, the Visual Studio team moved away from side-by-side components with the MSVC runtime in VS2010 because of the pain that side-by-side had caused in previous release.

So, in spite of all the options, I really believe that the best solution is to put all the DLLs in the same directory as the executable. If you can get over the folder looking untidy then it will make life much simpler. It is a trivial no effort solution to the problem.

Update

The update to your question provides the extra information that these DLLs are optional add-ons. In this case you simply have no alternative but to use explicit linking with LoadLibrary and GetProcAddress.

Puppis answered 13/12, 2011 at 22:19 Comment(3)
+1 Thanks for the info - given the particular scenario of this project (I will add comment on the question clarifying), the best solution would be to use the import method.Mapel
Remember that you need to replace every single procedure ... external with a variable holding the procedure, a call to LoadLibrary and a call to GetProcAddresss, and error checking. If you go down this route then wrap it up in a class to avoid duplication. I have such a library for situations where I can't avoid GetProcAddress.Puppis
That's the perfect type of challenge that I love to take on :DMapel
G
5

If you are dynamically loading the DLLs in your code, you can store them whereever you want since you have to pass the full path to LoadLibrary/Ex() anyway. If you are statically linking to the DLLs instead, then you can use SetDllDirectory() to designate an additional path to include in the OS's DLL search path.

Ganesa answered 13/12, 2011 at 22:58 Comment(5)
SetDllDirectory is only useful if you call LoadLibrary somewhere. No good for implicit linking from an exe.Puppis
If he's using DLLs to implement adds-on he can't use static linking.Splashy
SetDllDirectory() applies to both dynamic loading and static linking. The DLL search path is always used for static linking, as the OS loader only has the DLL name but not its path so it has to hunt for the file. For dynamic loading, the search path only applies if a non-absolute path is passed to LoadLibrary/Ex().Ganesa
@Remy - Does user code get a chance to call it before the OS loader tries to locate libraries?Education
@SertacAkyuz: It depends. For the main application, no. You would have to use redirection or a manifest to specify the DLL path. If you dynamically load a DLL that itself loads other DLLs (statically or dynamcially), then SetDllDirectory() can be used in the main app's code.Ganesa
P
4

You can do this with PATH but I recommend you don't. It's a brutal and inflexible approach. And of course you need to change the system wide PATH for it to have any effect at executable load time.

You can load your DLLs explicitly with LoadLibrary and GetProcAddress. That's no fun if there are a lot of imports but it can be a good option otherwise. And remember that if you go down this route, every single DLL must switch to explicit linking.

There is something called DLL Redirection but MS don't recommend you use that. They recommend that you use side-by-side components. Having said that, the Visual Studio team moved away from side-by-side components with the MSVC runtime in VS2010 because of the pain that side-by-side had caused in previous release.

So, in spite of all the options, I really believe that the best solution is to put all the DLLs in the same directory as the executable. If you can get over the folder looking untidy then it will make life much simpler. It is a trivial no effort solution to the problem.

Update

The update to your question provides the extra information that these DLLs are optional add-ons. In this case you simply have no alternative but to use explicit linking with LoadLibrary and GetProcAddress.

Puppis answered 13/12, 2011 at 22:19 Comment(3)
+1 Thanks for the info - given the particular scenario of this project (I will add comment on the question clarifying), the best solution would be to use the import method.Mapel
Remember that you need to replace every single procedure ... external with a variable holding the procedure, a call to LoadLibrary and a call to GetProcAddresss, and error checking. If you go down this route then wrap it up in a class to avoid duplication. I have such a library for situations where I can't avoid GetProcAddress.Puppis
That's the perfect type of challenge that I love to take on :DMapel
R
2

I would highly recommend that you leave the DLL's in the same folder as the applications.

If you really want to go down the road of putting the DLL's in a separate folder then you need to know whether you can load the DLL's with the LoadLibrary API which allows the specification of the path too. However, if the DLL's are statically loaded then it is Windows that performs the search. The Windows search first looks in the application folder then searches the Windows PATH. Also, as Delphi 7 only creates 32 bit applications this can get messy under Windows 64 bit.

Rizika answered 13/12, 2011 at 22:20 Comment(8)
No problems with 64 bit windows that I can see. Otherwise I could not agree more.Puppis
That just about answers my question - with my conclusion being to implement the ability to import them (which in my particular scenario would actually be a better choice anyway).Mapel
@David: in the past we have put shared DLL's into the windows\system32 folder. In Windows 64 bit, 32 bit applications do not have access to system32. See this link for more info: msdn.microsoft.com/en-us/library/aa384187%28v=vs.85%29.aspxRizika
No. 32 bit Windows has its own system32. When a 32 bit process access system32 the file redirector redirects to syswow64 which is the 32 bit system32 directory. And you shouldn't be writing to system32. That's owned by the OS.Puppis
Thanks David, but the point I was trying to make was that it's not as clear cut as it used to be under 32 bit Windows.Rizika
But in fact it is just as clear cut. If you are putting 32 bit DLLs in the 64 bit system folder then you are making not one but two mistakes. Cut that out and life is trivial.Puppis
As far as I know, the only time 64bit is any problem is if A) EXE and DLL do not match (one is 32 and other is 64), or B) DLL is placed in the wrong system directory (which I am keeping them out of the system directory)Mapel
@Steve: do not put anything into Windows system folders, especially if it's just application code and not system extensions. Consider them as OS private folders. It was a bad habit used in Windows 3.x for lack of ACLs and better options. IMHO Windows should not allow anything but approved by Microsoft to be written there.Splashy
A
2

On Windows, there is a "DLL search order". One of those search paths is The directory from which the application loaded, which is why it works to have them in the same folder as the EXE.

If you are statically linked to the DLLs, they must be loaded when the EXE is loaded into memory. This is before your first line of code is executed. So, you're relying on the DLLs being in one of the search paths. In this case, you're stuck with setting the path, and you must set it prior to the program loading.

If you are dynamically linking to the DLLs, then you can use LoadLibrary/LoadLibraryEx to load the DLLs at run time, in your code. Using those functions, you must specify the path to the DLL, so the DLLs could be anywhere. In this case, I feel that it's valid to put the DLLs in a separate folder to keep things tidy. As long as you don't put the DLLs into a shared location like the Windows System32 folder, you'll avoid a lot of headaches.

Adam answered 13/12, 2011 at 22:20 Comment(7)
If all you're providing is a search term and a link, this should be a comment instead.Annemarie
@KenWhite Actually a search term and/or link is perfectly fine as an answer in this case, the question begins mentioning that I would search by myself, if I knew what term to search for. But then again, this answer still isn't necessarily solving my issue, it's just providing some useful information to the subject.Mapel
@Ken, please post a link to this policy on comments vs answers so that I can educate myself.Adam
@David, I've added to my answer, please adjust your vote accordingly, and thanks for the warning before the downvote, Ken.Adam
@Marcus: Start with the FAQ, and then read this meta post. Answers should stand entirely on their own; if there's a link for further reference, that's entirely fine, of course, but the answer should be useful if the other site goes away or is down for some reason. I won't be downvoting after your edit, BTW, but since your edit pretty much just rehashed David's answer, I can't quite upvote it either. :)Annemarie
@Ken, I understand your concern now, but by answer worked without the link, so while it may have been only a partial answer, it was never just a link. Comments should be the same, and they should stand on their own. That's why comments like "that's incorrect" aren't good because answers change.Adam
Actually, it didn't work either way. :) The link posted didn't answer the question asked, and if you removed the link there was even less answer than before. But no need to discuss this further; I've posted suggested reading, and I guess we just have to disagree about the usefulness of your original answer. :) And comments do differ from answers; they're used to comment on the original question, or ask for clarification or additional information, or to provide suggestions that don't qualify as actual answers (like I think yours did).Annemarie
S
0

A temporarly solution is:

You can set your DLL path in your application's Shortcut (in "Start in" box).

Staves answered 15/4, 2016 at 17:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.