How to have a DLL work on different Windows versions?
I'm compiling my own DLL comprised of several .o
files. One of the .o
files has a function that calls SHLoadLibraryFromItem
that is supported on Windows 7 only. The function is never called unless the application that uses the DLL is running on Windows 7. (Yes, I'm sure.)
However, when running the application on an older version of Windows (say, XP), the entire application crashes upon launch with an error "The specified procedure could not be found." Although the error doesn't specify which procedure could not be found, if I comment out the call to SHLoadLibraryFromItem
, then everything works fine.
Questions:
- Why is Windows attempting to find
SHLoadLibraryFromItem
even though it's not being called on XP? - Is there any way to have Windows not do that, i.e., find
SHLoadLibraryFromItem
only when running Windows 7, i.e., some kind of lazy binding? - If not, what's the best way around this?
The only way's around this that I can think of are either:
- Use
LoadLibrary
to load the Windows DLL thatSHLoadLibraryFromItem
is in and useGetProcAddress
to obtain the address manually into a pointer-to-function and use the pointer to callSHLoadLibraryFromItem
instead? - Have two DLLs: one that contains functions that are supported for Windows 7 that will be loaded only when running o开发者_如何学Cn Windows 7.
Any other ideas? I'd really prefer some kind of lazy binding as mentioned above.
Update
PLEASE READ WHAT I ACTUALLY WROTE. I clearly stated in the first paragraph that SHLoadLibraryFromItem
is not called unless I KNOW FOR CERTAIN that the application ACTUALLY IS RUNNING ON WINDOWS 7.
The application crashes merely when the DLL is loaded.
The linker embeds a reference in your modules to every API function that's used. when the Windows loader loads your executable and its modules, it needs to "hook up" all the calls in your code to the locations in memory where the API functions are actually loaded. If it can't find them, it won't continue.
Using LoadLibrary
and GetProcAddress
is the "standard" way to get around this problem.
Using two DLLs doesn't help you, because as long as one of them fails to load your app will still not start. You could get around this by using delay-loading, putting all the code that depends on a new O/S in a separate module and wrapping all the calls to that module in Win32 SEH exception handlers (you get an SEH exception when delay-loading cannot load a module). The advantage is that you can use the "automatic" linking without the mess of function pointers, but the exception handling can be pretty nasty.
This article explains a bit and gives some examples of how to wrap this up neatly.
Why is Windows attempting to find SHLoadLibraryFromItem even though it's not being called on XP?
Windows resolves references when the application is loaded into memory, not when a call is made. This is called "dynamic linking" (as opposed to static linking with a Linker), but it is not truly dynamic. Therefore, it does not know whether the a particular method will be called during runtime or not.
精彩评论