Use two different versions of a .lib file in one C++ project? - c++

I'm working on a Volume Shadow Copy program. I have just found out that I need to use a different set of .h files (vsbackup.h) and associated .lib files (vssapi.lib) to compile the project for Windows XP (in comparison to Vista and 7). This is due to a series of subtle changes in the .h files: in XP, a call such as CreateVssBackupComponents() was a call into the API (there was only the declaration in vsbackup.h); the more recent vsbackup.h changes this into CreateVssBackupComponents() { CreateVssBackupComponentsInternal(); } and when I compile my project with the newer .h and .lib files and run the program under XP, it says
The procedure entry point "CreateVssBackupComponentsInternal" was not found in DLL "vssapi.dll".
Is there any possibility to incorporate these two different lib files in one project, so that I don't have to compile two different versions of the program?

If you need to work with two different versions of the dll (because if I understood correctly the problem lies there, the different lib/headers are just the tip of the iceberg) you should dynamically load it with LoadLibrary, check the presence of the entrypoints you need with GetProcAddress and call the functions you need with the function pointer that it returned.

You can also create two project configurations one for XP and one for newer Windows versions. Then add both files to your installer and let the installer check which Windows version it is installing at and select the right version of your program.
(That's basically what I did when I had your problem)
The more proper solution though would be putting it in a DLL, create two versions of that DLL and then runtime check and load the right DLL. That way a Windows update wouldn't cause problems.

Personally, when libraries start to get a bit /crazy/, I start looking into giving the problematic libraries their own process, and use some sort of RPC to interact with them.

Related

Choosing from multiple DLL versions

Today I build my application and packaged the installer with QtIF. It worked nice on my computer but complained about missing msvcp140_1.dll in another computer.
Then I run find . -iname "msvcp140_1.dll" and found more than five different ones on my computer, I checked the md5sum.
Then I spend the time to try all of them on the other computer and all seem to work fine. No more complains about missing DLL.
How should I choose between the DLLs? Just pick any seems too easy.
Is there someway to inspect the DLLs, to check for a version?
I believe that DLL was a dependency from another binary included in my application, was not that the QtIF failed to include it.
Call the MS Redist Installer from your Installer. This can be done quietly, so that the end user does not notice it.
Find the vcredist_x64.exe file (or vcredist_x32 for 32 Bit applications), add it to your installer,
let it extract to the "TEMP" folder
and then call vcredist_x64.exe /quiet at the end of your install.
This has several advantages:
You will definitely copy all required files to the users computer.
Should new versions of the runtime library be released by Microsoft and should they already be on your users computer, your code will use the newer versions, which may include bugfixes.
Windows Update may also update the libraries.
That said, it is possible to copy the DLLs themselves, but you should make sure
a) you choose the right ones
b) they come from a trustworthy place, i.e. your VS installation folder
c) reside in the same directory as the executable - otherwise you will run into trouble with manifests.
The reason you might want to include the DLLs directly is if you want to reduce the overall size of your installer.
We did this a couple of years with our products, but finally gave in and simply used the vcredist_x64.exe, even if that increased the installer binary another couple of MB in size. But in the long run that's the easiest way.
I think (not sure), msvcp140_1.dll is an additional DLL for the VS 2019 runtime. VS 2017 runtime does not need this, but the new one does.
The non-redistributable method is to ship the DLL's that come with your compiler, i.e. the compiler that built your executable. After all, the DLL will be loaded into the same process as your EXE. It's only logical that these should match.
You'll find those DLL's in \Program Files*\Microsoft Visual Studio *\VC\Redist

How can I control search order for DLLs to avoid hijacking?

As a background: my application requires:
admin privileges
access to WinAPI DLLs
be able to run on all OSs: Win7-Win10
Normally, to use API, I can just link required *.lib files. However it uses default search order, that means (according to https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) it firstly loads DLLs from "The directory from which the application loaded."
As a result, if the DLL exists in the same directory, running my app by double-click loads also that DLL.
I want to look for DLLs only in system directories (similarly to https://stackoverflow.com/a/46182665/9015013 ).
I know I can try to create some kind of proxy, like
BOOL WinAPIFunction(WinAPIType param) {
return reinterpret_cast<decltype(&WinAPIFunction)>(
reinterpret_cast<void*>(GetProcAddress(manually_loaded_module, "WinAPIFunction")))(param);
}
But it is hard to maintain all these functions. Is there any better method to force windows to look only in system32? I thought about manifest file but it requires version for each DLL that can break "capability" requirement (DLLs have different version for Win7 and Win10)
The solution is posted by #Eryk Sun in comment above.
It is sufficient to add all DLLs not listed in known dlls to delayed loaded libraries and call SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); at the beginning of the WinMain.
Thanks
You can try to use "Known DLLs" feature: If Windows "knows" that DLL, Windows doesn't search dll file. Known feature is described into link, you written in question.

Can two independent Qt applications use same DLL files?

I'm having a difficult problem to solve. I'm having two Qt-based applications, first one is in the main folder and the second one is located in it's subdirectory (yes, I'm forced to have it this way). The issue I'm facing is that I have to deliver 5 exact the same DLL's files for each application. I wouldn't have problem with that, if they wouldn't weight so much (10 DLL files = 60~ MB). Which is, definately too much.
On my debug build I am able to set the PATH variable within Visual Studio settings, and I will be not able to do so on production machines.
Is there any way I could set one of those application to rely on DLL files located in subdirectory?
I don't know what kind of an installer you're using, but the dlls should be stored only once in the archive, and the files should be hard linked on installation. So it's a non-issue unless your installer is broken or the install script is.

Where to install SDK DLLs on a system so that they can be found by apps that need them

I've got an SDK I'm working on and the previous developer just dropped the DLLs in System32 (Apparently a serious offense: see here)
So assuming I move them out into \Program Files\\SDK (or whatever), how do I make sure that all the apps that needs those DLLs can access them? And to clarify, all apps that access these are doing early (static) binding to the DLLs at compile time so I can't pass the full path to them or anything. They need to be able to find it just given the DLL filename only.
Along the same lines, what about including a particular version of MSVCR80.dll? They all depend on this but I need to make sure they get a specific version (the one I include).
Any ideas?
An SDK is by definition a development kit. It's not a deployment patch...
What this means is that the applications that depend on those assemblies should ship with them and install them into their local \program files.. directories.
The reason for this is let's say you decide to do a breaking change by eliminating an entry point for example. By installing your "SDK", it has the potential to stop older programs from functioning.
You could take a play from the Java handbook and update the PATH environment variable. Whenever a program makes a call to an external assembly it searches along that environment variable until it finds it.
Of course, this could still result in the problem showing up. So your best bet is to just install the SDK into Program Files and let the developers of the products that depend on your toolkit decide whether they want to update their versions or not.
UPDATE
As I'm thinking about this, one last possibility is to GAC your assemblies. In the event you do so, bear in mind that they should be strongly named and properly versioned so as not to step on each other. I don't recommend this route because it hides the actual locations of the assemblies and makes uninstalling a little more difficult then simply hitting delete on your directory.
I can't tell you about your own DLLs, but you should never redistribute Microsoft DLLs alone.
You always have to use Microsoft Redistributable Package.
For example, if your application depends on dll from Dev Studio 2005 SP1, you should redistribute your application with Microsoft Visual Studio 2005 SP1 redistributable. The same applies to 2008. MS provide MSI based installer and Merge Module to include in your own product installer.
You are asking about "DLL Hell", something I had thought every Windows developer was familiar with. The order of search for DLLs is:
the directory the exex that calls them was loaded from
the current directory
various Windows directories (as discussed in your previous question)
directories in the PATH variable
As the Windows directories should be ruled out, that leaves you with three options.
You can put your install path in the search path, which will allow the applications to find them.
Alternatively, you can deploy the DLL's into the same directory as the application that depends on them.
I believe the first is better from an SDK perspective - it'll make development easier. But I think the second is better for when the application gets deployed to end-users, unless you expect there may be many consumers on a single system so the disk and memory footprint of having copies of the DLL are prohibitive.
If you can't install the dlls into the same directory as the exe using them you could append your directory to the PATH environment variable.
You don't say which version of Windows you're using, as the details are slightly different from what I remember.
You could also put your version of MSVCR80.dll in the same folder. However, you'd have to ensure that your folder was before the system one on the path otherwise the linker would pick up the "standard" one first. However, if you adopted the "local" dlls approach then you wouldn't have this problem as Windows searches the local directory first and so will pick up your version of MSVCR80.dll.
Is your version the latest or a previous version? You might be better off getting your app to work with that version or later and then allow the users to update their machines as required. This also illustrates why you should never mess with the dlls in \Windows or \Windows\system32 as, as others have pointed out, you could break other applications by changing the version of this dll.

How to link a .DLL statically?

We have a (pure native C++) .DLL that is build by VS. As clients we have some native C++ applications and a .Net-Wrapper around this DLL written in C++/CLI. Finally there are some client applications for the .Net-Wrapper written in C#.
My problem is that the native.dll must be distributed in a different way than the .Net world works and the VS does not keeps track of that DLL.
So to let all my C# Apps work correctly I have to copy it to each executable directory or put it somwhere in %PATH% (which I would avoid on developer computers since they may want to start different apps with different versions of the DLL).
Even bigger problems occur if there are UserControls that reference the Wrapper-DLL: You have to copy the DLL to VS's directory or again to %PATH%.
But the worst case occurs with our Translator tool. This tool keeps track of .Net-Assemblies and packs them into Translator-packages that can be send to an external translator. As far as I know there is no way to put the native .DLL into that package!
So I plan to link the native DLL statically into the .Net-Wrapper which would solve my problems.
But for our Native applications this native DLL must still be a DLL.
So I have two options:
Make two projects of that (one that generates a static library; and one that creates a dynamic one => I try to avoid this)
Find a solution to link DLLs statically
Find a way to let VS generate two outputs from one project
In the C++ project file for the dll, create two configurations, one that generates a DLL and one that generates a .lib. Two projects are not necessary, since any .NET/C++ project can support multiple build configurations (this is how Release and Debug versions build differently).
Another option is to have two projects, one project will output a .lib which can be statically linked, and a second project which will output a .dll and will have your .lib as dependency, you should add .def to your .dll with the symbols that you are planning to export, or else it will be empty.
Pick up a copy of DLL to Lib (Edit: If you can't find a cheaper option)
You can generate a dll and export the entry point to a lib using dllexport, this is explained here
http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx