Analysing CRT Dependencies in a DLL manifest - c++

I am using Visual Studio 2005 to build a DLL. By opening the DLL in a text editor I can see that it refers to multiple MS CRTs as follows. How can I find the name of DLL which the dependency elements refer to? I am trying to specifically find the source of the dependency which links to the 8.0.50727.5592 version of the CTR, it is the last one.
Any ideas?

Most likely, you're getting the dependency injected automatically because you're linking against a 3rd party library that uses a different version of the runtime that you're using. Check the libraries against which your dll links and most likely one of them will have the exact extra dependency that you have there. By the way, you can use VS2005 to open a dll and look at its embedded manifest.

I know it's an old post but I had the same issue and found a great tool to list all dependencies for any included libs. I use VS 2010:
In command prompt, go to Microsoft Visual Studio 10.0\VC\bin and run command:
link /dump /directives libpathandname.lib
This will list out all linker dependencies including exact CRT versions.

I'm not sure whether it will tell you exactly what you need in this instance, but Dependency Walker may shed some light on it. It'll show which of the dependent dlls depend on the CRT and it may show the versions from the manifests, though I'm not sure.

Related

Visual studio 2015 run-time dependencies or how to get rid of Universal CRT?

Compiled couple of .dll's using visual studio 2015, and tried to deploy on some older windows 7 / 64 bit. Tried also to guess which dll's are needed for application to start and copied MSVCP140.DLL & VCRUNTIME140.DLL - but application could not load vs2015 dll. Started to analyze what is wrong - and dependency walker showed dependencies from following dll's:
API-MS-WIN-CRT-MATH-L1-1-0.DLL
API-MS-WIN-CRT-HEAP-L1-1-0.DLL
API-MS-WIN-CRT-CONVERT-L1-1-0.DLL
API-MS-WIN-CRT-STRING-L1-1-0.DLL
API-MS-WIN-CRT-STDIO-L1-1-0.DLL
API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL
API-MS-WIN-CRT-FILESYSTEM-L1-1-0.DLL
API-MS-WIN-CRT-TIME-L1-1-0.DLL
This was especially surprising since to my best understanding CRT is responsible for starting dll/exe, it does not provide any higher level services.
Ok, tried to figure out how to get rid of them or at least to minimize.
Found one article:
https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/
It mentions about release static libraries - so I thought that I could link against them and get rid from *L1-1-0.DLL* dependency hell, but no matter what I have tried - I had no success. I've tried to link against libvcruntime.lib, libucrt.lib, libcmt.lib, tried to disable using linker option "/nodefaultlib:vcruntime.lib", and even tried to add include directory $(UniversalCRT_IncludePath), and also overriding some of define's as I have tried to guess they works - none of my attempts helped.
As an intermediate solution I've fall back to using Visual studio 2013, where CRT dll's are only two: msvcp120.dll, msvcr120.dll.
Of course you will probably recommend to install Visual studio 2015 run-times, but one of our requirement is to support standalone executable - which works without any installation - so additional installation is out of question for now.
Can you recommend me anything else than to wait Visual studio 2017 to arrive ?
No, you can't get rid of them, but I was able to statically-link to them by setting the
C/C++ > Code Generation > Runtime Library compiler option
For Debug: from /MDd to /MTd
For Release: from /MD to /MT
This removed all the API-MS-WIN-CRT-* and runtime dll references and caused all the CRT code to be statically linked.
Details on the new VS2015 Universal CRT (dynamic and static) are here:
https://msdn.microsoft.com/en-us/library/abx4dbyh.aspx
Note that the only other option is to compile with an older-compiler (like virus developers),
not newer, because Microsoft promises same UCRT-requirements for any newer compiler-version as well.
I too was fighting with statically linking a solution with multiple components/project library dependencies importing functions from various parts of the MSVCRT, UCRT and Kernel. The hope was the resulting EXE could be just copied around where it was needed (it was no product which would justify a full MSI installation).
After almost giving-up I found the best solution was the follow the guidelines hidden in the Universal C Runtime announcement, specifically:
We strongly recommend against static linking of the Visual C++
libraries, for both performance and serviceability reasons
Just remove all the "special" linker options you tried, drop-back to /MT|/MD (Multi-Threaded CRT DLL Release|Debug) runtime library choice and it works everywhere, e.g. newer Windows 10 workstations, 2012 R2 servers and Windows 7). Just install/redistribute MSVCRT (VC_Redist*.exe) and KB2999226 (UCRT via Windows Update) as Microsoft tell us to do, because as they also say:
The Universal CRT is a component of the Windows operating system. It
is included as a part of Windows 10, starting with the January
Technical Preview, and it is available for older versions of the
operating system via Windows Update.
So logically the only additional deployment dependency our C++ solutions add for the customer is the MSVCRT, because the UCRT should already be there on up-to-date/well maintained machines. Of course it adds a bit of uncertainty; you can't just copy the EXE and run on any machine, good or bad.
If you produce a decent deployment package like an MSI then it's straightforward to include when you have tools like WIX. Also to note is since the recent SDK you can include the 40-odd DLLs locally, but that doesn't satisfy the security update principle so I wouldn't do that.
This is really the only supported way to do it, see another example here. This article also suggests we link against "mincore_downlevel.lib" which is an important tip, crucial to whether you get these "api-ms-win*" missing DLL errors. For example:
Project SDK version set to 10, link with mincore.lib = Runs only on Windows 10, but not 8.1/2012 R2 or Windows 7/2008 R2 server.
Project SDK version set to 8.1, link with mincore.lib = Runs on both Windows 10 and 8.1/2012 R2 server, but not Windows 7/2008 R2 server.
Project SDK version set to 10, link with mincore_downlevel.lib = Runs on all!
In summary:
Do not link statically, leave the default DLL C runtimes selected in the project settings.
You don't need the old SDKs, can develop with the latest Windows 10 SDK, but you must link with "mincore_downlevel.lib" not "mincore.lib" if you want to support older Windows versions.
For ease of use, add this to your targetver.h or stdafx.h which also documents your choice (remove the other line):
// Libraries
#pragma comment(lib, "mincore.lib") // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
(Updated 11.10.2016).
It's possible to get rid of universal CRT by linking it statically, I'll get to it later on, but let's take
a look if you continue to use universal CRT as such.
According to article https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ -
it's possible to launch your application using universal crt dll distributables from following folder:
C:\Program Files (x86)\Windows Kits\10\Redist\ucrt
There are 41 files totally in list with 1.8 Mb size in total. (example for 64-bit platform)
Of course it's not enough, you will need additionally vcruntime140.dll & msvcp140.dll coming from following folder:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT
So after that you will ship totally 43 additional dll's besides your application.
It's also possible to statically compile ucrt library inside your application after which you will not need 43 dll's -
but whether static link will for after linking or not - depends on your application - how many dll's and which api's are in use.
Generally after ucrt gets linked into two different dll's they don't necessarily share same globals with each other - which can results in errors.
You need to link against vcruntime.lib / msvcrt.lib, but it's not sufficient - there are extra _VCRTIMP= and _ACRTIMP=
defines which needs to be disabled from pulling functions from ucrt.
If you're using premake5 you can configure your project like this:
defines { "_VCRTIMP="}
linkoptions { "/nodefaultlib:vcruntime.lib" }
links { "libvcruntime.lib" }
followed by:
defines { "_ACRTIMP="}
linkoptions { "/nodefaultlib:msvcrt.lib" }
links { "libcmt.lib" }
Defines are not documented by Microsoft - so it's possible that it's subject to change in future.
Besides your own projects, you will need to re-compile all static libraries which are in use in your projects.
As for boost libraries - I've managed to compile boost as well, using b2.exe boostrapper
boost>call b2 threading=multi toolset=msvc-14.0 address-model=64 --stagedir=release_64bit --build-dir=intermediate_64but release link=static,shared --with-atomic --with-thread --with-date_time --with-filesystem define=_VCRTIMP= define=_ACRTIMP=
When troubleshooting linking problems - notice that unresolved __imp* function names from because of dllimport keyword usage -
and if you link against libvcruntime.lib, you should not have any __imp* references.
I was too struggled a lot finding out the run time DLLs required to run an application which was built in Visual Studio 2015.
Here I found the following things which allow VS-2015 built application to run.
Download the redistributable from https://www.microsoft.com/en-us/download/details.aspx?id=52685
Place the msvcp140d.dll, vccorlib140d.dll, vcruntime140d.dll & ucrtbased.dll.
Note : Place the dlls versions according to your system processor's architecture(x86, x64..).
Setting: Configuration Properties - Advanced - Use of MFC - "Use MFC in a Static Library" worked for me (with a console application - not a MFC/ATL application per-se).
If you're not trying to replace the Runtime with your own then it doesn't matter whether
You have Runtime Typing enabled/disabled
You have C++ Exceptions enabled/disabled
Whether you have the Runtime Library set to Multithreaded DLL or not (setting it to non-DLL is still building it into your binary)
The only thing you need to ensure is that you don't use any of its capabilities and Visual Studio automatically doesn't link to it. Ie. No asserts, no calls to anything in string.h or stdio.h, nothing. Anything the compiler can replace with its own intrinsics tho is ok, as are compiler checks like static_assert.

Compile C++ in VS without requiring MSVCP120D.dll at runtime

I'm trying to make a binary that can be run on any windows machine without the visual c++ stuff installed (I'm assuming that's what MSVCP120D.dll is however my searching was not very fruitful as to what this actually is). I made a game for an assignment and wanted to have other people (non-devs without VS stuff installed), help me test it but they kept getting errors saying that the above dll is missing. I'm not using any Visual C++ stuff and have the /Za flag set to ensure that it's just ANSI C++. Does Visual Studio support compiling ANSI C++ and if so how do I go about making it not use Visual C++ stuff, if it doesn't support this what compiler should I use?
As you can see here, the MSVCP DLL is the platform's implementation of the C++ Standard Library. In short what that means is you cannot distribute your application without needing the "stuff" that these libraries provide. All compilers regardless of platform would need some kind of implementation of the Standard Library. Typically this is distributed in the form of libraries.
However you can distribute your application so that the "stuff" is built in to your program directly, rather than being shipped in a separate DLL. In order to do this, you must statically link your application to the Standard Library.
There are a few ways to accomplish this. One way is in Project Settings. In "Project" > "Configuration Properties" > "C/C++ Code Generation" > "Runtime Library", choose "Multithreaded (/MT)" as opposed to "Mutithreaded (Static)".
By the way, the "D" in "MSVCP120D.dll" you mentioned above means "Debug." This means that you are trying to distribute a debug build of your program. You should (almost) never do this. Distribute release builds instead.
You have three options (in the order I'd recommend):
Don't statically link, instead get people that want to run your game install the visual studio re-distributable package. 32-bit VC 2010 version here: http://www.microsoft.com/en-us/download/details.aspx?id=5555
Statically link the CRT (the dll you don't want to require at runtime) see here for details: How do I make a fully statically linked .exe with Visual Studio Express 2005?
Build an app that doesn't even use the CRT at all. Here you will have to implement your own operator new that calls HeapAlloc(), and operator delete that calls HeapFree(), its an interesting challenge ;). To do this you tell the linker to ignore all default libs.
Build with the static runtime libraries rather than the DLL versions.
Go to Properties, C/C++, Code Generation, Runtime Library and select /MTd or /MT rather than the /MDd and /MD options.
Configure your project to link against the runtime statically rather than dynamically.
First of all the D on the end of the name indicated a debug build. If you make a release build then it will need it without the D. This is important because microsoft do not allow the debug libraries to be distributed without visual studio.
The machine you are trying to run the program on may already have the release runtime installed as lots of programs use it. If not then install http://www.microsoft.com/en-us/download/details.aspx?id=30679 on the machine ( I think that's the right one but can't check at the moment)
You'll want static linking, that 'builds in' the external library calls into your binary. It does have the added affect of larger binary file, but in your case that doesn't sound like that big of a deal.
On a side note, MSVCP120D.dll is the Microsoft Visual C++ 12 debug DLL (dynamic link library) that contains all of debug C++ libaries (i.e. iostream, string, etc). That library is what you would be 'baking in' to your final binary.
Hope that helps.
I encountered this error when I tried to execute my exe on a different machine that had a newer version of Visual Studio on it. You need to change the project properties and re compile in order for this to go away.
To do this:
Open up solution that you are trying to run
Right click on the Project file - > Properties
In Configuration Properties and General, Ensure Platform Toolset is configured to be the correct compiler on your machine. If it is not correct, it should give a message next to it saying that it's not installed.
Build and run the code again and you should no longer get the issue.

How do I now which DLLs are part of C++?

I've opened up my program in Dependency Walker. It shows the following DLLs:
GDI32.DLL
OLEAUT32.DLL
IMM32.DLL
WINMM.DLL
KERNEL32.DLL
USER32.DLL
SHELL32.DLL
OLE32.DLL
ADVAPI32.DLL
WS2_32.DLL
MSVCP100.DLL
MSVCR100.DLL
So I'm guessing half of those are part of Windows and the other half is part of C++, right? What is the best method to find out which are part of the OS and which aren't?
Don't package up any DLLs that you didn't explicitly add into the project yourself.
Read the documentation for your toolchain (Visual Studio, or whatever) to find out if there are any redistributables that you need to include in your package. Those may include some DLLs.
If you are not allowed to publish an installer (the form of which is generally taken by said redistributables for Microsoft products), then you shall not simply manually dump DLLs instead. You shall remark in your release notes that those dependencies must already be installed on the target system. You make them a pre-requisite for your application.
MSVCP100.dll and MSVCR100.dll contain the runtime libraries for C and C++. Everything else in the list belongs to windows. One way to determine if a DLL belongs to windows is to look at it's path (c:\windows...) and then check for a digital signature from MS. It's not foolproof but it'll get you a bit closer to determining if the DLL belongs to windows or not.
Edit: See this answer by Lightness Races In Orbit concerning distributing Windows DLL's
Other than looking them up using Google, there's probably no easy way to tell. However, in this case I can tell you that MSVCP100.DLL is the C++ standard library code, and MSVCR100.DLL is the C runtime library.
Dependency Walker itself has list of 'known system DLLs'. You can find it in Options -> Configure Module Search Order menu.

Removing msvcp90d.dll dependancy from Windows binary

I have a dll that I distribute that will not run on some windows OS. Using dependancy walker I discover msvcp90d.dll missing on these systems. I DO NOT want any run time dependancies that require the C++ redistributable, and since the application that calls the DLL is not written in C++, it does not have any dependancy on the C++ redistributable.
I am guessing the I left the DEBUG option in the linker preferences on when I compiled the dll which is why it needs msvcp90d.dll?
ADDED:
Appologies, I pasted the wrong dll name in my original question.... too many hours in front of the monitor...
THe dll is a third party dll that I did not write compiled by me in VS2008.
MSVCP90 is nothing to do with debug (that'd be msvcp90d). You can remove your dependency by switching the compiler to /MT (instead of /MD). You also need to ensure that every static library you link to was also compiled /MT.
I recommend against building apps /MT because it has a significant negative effect on system performance and makes servicing take longer in the event of a security issue with the CRT.
Finally, note that /MT means that your CRT is private. So you must ensure that CRT/STL types don't pass across your DLL boundary.
Martyn
Your options as I see them:
Compile the DLL with the /MT option to use static linking to the C runtime.
Continue with dynamic linking to the runtime, but distribute the C runtime with your app.
It needs MSVCP90.dll because the dll was compiled with Visual Studio 2008 most likely. That is the release runtime. The short answer is if you don't want C++ runtime dependencies don't use C++ libraries or applications.
However you can do any of the following to solve your problem:
Install the redistributable to the target system to satisfy the dependency
Remove the dependency on that dll from your application
Recompile the dll against the version of VC you prefer that is already present on the target system

Alternatives to including MS C runtime distro?

I use MSVS 2010 and MSVC++E 2010 to build my applications in C++ and I've notice a lot of my friends (who test my apps on their PCs) don't have the Microsoft C++ runtime library installed on their computers. I've started including the Microsoft C++ redistributable package with my apps, but this seems unnecessary. Would I be able to instead include the libraries in my executable directory? I know that one of the libraries used is msvcr100.dll, but are there also others I need to include? Or is the redistro my best option?
in your project options, for code generation, you can choose the STATICally linked libraries instead of the DLL versions. That eliminates the need for an external dependency like this, at the cost of a larger EXE.
You don't necessarily need to HAVE to have the runtime library within your executable directory, you may use a Manifest File that has a relative path which points to runtime if you wish. But yes, you can include the libraries within the install of your application.
I think we lug around the msvcr as well as the msvcrt and the msvcp DLLs which now that I'm writing that out, might be a bit overkill.
When you build your application to a static runtime, you don't need to distribute the runtime dlls.
Otherwise you have to include the Microsoft runtime.
Links to runtime installers for Visual Studio 2010
Compiling your project with /MT solves the distribution problem. Be careful though, it can get you in trouble when you use DLLs. They will have their own memory allocator. If they export a function that exposes a pointer or a C++ object that needs to be released by the client code then you'll have a very hard to diagnose memory leak on your hands. Very easy to do, just return an std::string for example.
Anyhoo, the setting is found by right-clicking the project in the Solution Explorer window, Properties, C/C++, Code generation, Runtime Library setting.
Also note that VS2010 supports local deployment. Just put the msvcr100.dll file in the same directory as your EXE. You also need msvcp100.dll if you use STL or iostreams.