Inspecting a .exe to understand with what version of Visual C++ it was built - winapi

Is there a way to check what version of Visual C++ was used to build a given .exe?
I know that if the .exe uses dynamic link with CRT that is easy: I can just use Dependency Walker and read the MSVCRxx.DLL version, e.g. a dependency on MSVCR90.DLL means that the .exe is built with Visual C++ 2008 i.e. VC9; but what about the case of static linking with CRT?

Is possible check linker version in Depends.exe, is almost identical as VisualC++ version.
In lower view in Dependency Walker, select column Linker Ver.

I found this interesting article on MSDN by Matt Pietrek:
Inside Windows: An In-Depth Look into the Win32 Portable Executable File Format
The fields of interests are IMAGE_OPTIONAL_HEADER32/64::MajorLinkerVersion and MinorLinkerVersion. They are almost identical to Visual C++ version (e.g "10" and "0" for VC10).
(I think these are the fields that Dependency Walker uses for the Linker Ver column in its user interface.)

Related

What is __CxxFrameHandler4 and what does linker error "unresolved external symbol __CxxFrameHandler4" mean, exactly?

I'm using several libraries built through vcpkg (such as civet-web and prometheus-cpp), against my Visual C++ projects. When building x86 all is perfect, in x64 I get a bunch of linker errors:
error LNK2001: unresolved external symbol __CxxFrameHandler4
Searching online all references to this symbol/error are about specific projects, I cannot find what __CxxFrameHandler4 is and what problem this error is highlighting. I don't know if it's a problem with the way vcpkg is building the library, or a problem in my project or how to start looking for a solution.
I did find this blog article but it is in reference to a preview of VS2019, I cannot find any settings related to it: https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/
If anyone can explain what this is all about it would be a big help.
I faced the same issues when trying to install and use cpr with vcpkg. I wanted to use cpr library in a VS2015 project.
Reason: I had VS2019 installed. vcpkg uses latest version of toolset Visual Studio.
Resolution: Add your own triplet or change existing such a way that your specified toolset is used. Adding did not work in my case so I changed existing "triplet" files in triplet folder in vcpkg. I wanted vcpkg to use toolset that comes with VS2015 (It's V140)
Content of x86-windows.cmake file
set(VCPKG_TARGET_ARCHITECTURE x86)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)
set(VCPKG_PLATFORM_TOOLSET "v140")
set(VCPKG_DEP_INFO_OVERRIDE_VARS "v140")
Content of x64-windows.cmake file
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)
set(VCPKG_PLATFORM_TOOLSET "v140")
set(VCPKG_DEP_INFO_OVERRIDE_VARS "v140")
A more general answer is that this happens if you are mixing objects that were built with different platform toolsets, e.g.,
Visual C++ 2015 (v140)
Visual C++ 2017 (v141)
Typically, you (or someone else) may have built a dependency of your project with a different compiler version (platform toolset), and the fix it to change the platform toolset of either your project or the dependency (or use the correct build of the dependency, if you used a pre-built package)
I think you pointed out the right article which is
https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/
I faced a similar issue in linking 64-bit library built with VC143 toolset with a 64-bit Application built with VC141 toolset.
After adding the following properties to VC143 built static library project, I was able to build the application. This disables the new feature mentioned in the above article (Exception Handling Smaller)
VS2019->Properties->C/C++->Command Line add '-d2FH4-'
VS2019->Properties->Linker->Command Line add '-d2:-FH4-'

How can I check the LIB file version?

After reinstalling Visual Studio 2010, I recompiled the code and encountered the following error:
Error 'LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt'
A solution mentioned that the lib file is incompatible and I need to install Visual Studio 2010 SP1. I did that, and now it has been solved.
I am wondering how can I check whether a lib file is created by SP1 or not?
I tried dumpbin, but I cannot find the version in its result.
It was not an incompatibility with your LIB file that caused the problem here, so checking the version of the linker that created it would not be a solution anyway.
The issue is that cvtres.exe (used internally by the linker toolchain) depends on a particular DLL (msvcr100_clr0400.dll) shipped with VS 2010 RTM. When you update to a later version of the .NET Framework (e.g., by installing .NET 4.5 or installing a later version of VS), this DLL is replaced. That stops cvtres.exe from working.
The reason why installing VS 2010 SP1 fixes it is because it actually modifies the cvtres.exe application to break the dependency. And now that all pieces of the linker toolchain work, you can compile and link the code without error.
Of course, there are other problems you can have when you start mixing libraries created by different versions of the compiler and/or linker. They aren't guaranteed to create 100% compatible output, so mixing them is not supported (at least not between major versions, I'm uncertain about how this rule applies to service packs).
In general, it's best to just recompile all libraries whenever you update your build system. The only time you wouldn't do this is if you didn't have the source code, in which case, you need to be very careful about updating your build system, lest you introduce gratuitous incompatibilities.
As far as determining the version of the linker that prepared a particular binary, using dumpbin.exe (included with the SDK) is exactly the correct approach. For static libraries, run the following command from the Visual Studio SDK Command Prompt:
dumpbin /rawdata:1 MyLibrary.lib
You'll see the assembly manifest, which will include the full path to the compiler used to build the library as well as the version of the CRT that it depends upon.
For dynamic libraries (i.e., DLLs) and executables, run the following command:
dumpbin /headers MyApp.exe
Look under the "Optional Header Values" section (not actually optional) for the version of the linker, along with a timestamp of when it was generated.
Note that you're very unlikely to find this information in release builds of a library or binary.

Visual Studio 2010 Runtime Libraries

I wrote a tool that many users would use on their computers. I noticed however, that users who do not have visual studio installed, cannot open my executable. The error says that msvcp100.dll is missing. I found in internet a redistributable package from microsoft, that should apparently provide these dlls. My question is: is there another way to bypass this problem? Something like an option in the project properties?
Yes, you can change a compiler setting to link the C++ standard library classes into your program instead of having a dependency on the DLL. Right-click your project in the Solution Explorer window, Properties. Switch to the Release configuration (upper left). C/C++, Code Generation, Runtime Library setting. Select /MT.
Only do this when you only have a single monolithic EXE. When you use your own DLLs then you really need msvcr100.dll and msvcp100.dll so that the runtime library gets shared between all modules.
It is part of C++ runtime and the target machine needs it. THere are couple of ways to address it.
Please check following link from Microsoft MCVCP100.DLL

remove dependency on CRT in dll

I'm building a dll on Visual Studio 2010, and I'm using some simple C functions like fprintf and fread, and it's linking to msvcr100.dll by default.
This dll is going to be loaded into an app that may be using a different CRT version (eg. msvcr90.dll, msvcrt.dll).
Since I know the app's going to load a CRT before my dll gets loaded, can I remove the dependency on msvcr100.dll and use the C functions in the CRT loaded by the app?
In the end, I decided to build the DLL against the lowest common denominator CRT version used by the target app, msvcr90.dll.
I did this by using the MSVC toolchain, available with Visual C++ 2008 Express (free).
I did try the mingw/gcc toolchain, which allows you to specify which CRT version to link against (see mingw-rt and gcc -specs=msvcr**), however, msvcr90.dll is a new-style SxS assembly so I couldn't get the produced executable to run properly.
It may be worth considering skipping linking against msvcr**.dll entirely; see this post and VC/include/delayhlp.cpp.

Which runtime libraries to ship?

I work on C/C++ using Visual Studio 2008. I believe that I am not concerned about which runtime libraries are being used by my code as I have the developer setup. But when the executable is shipped, the runtime libraries being used need to be shipped alongwith. Am I right?
If yes, how can I identify which shared libraries are actually getting used? Or are there any libraries that we can ship without having to know this?
You're correct, you need to ship a version of the C runtime libraries that matches the version you linked your application against. If you're compiling with Visual Studio 2008, then you want to use the Microsoft Visual C++ 2008 Redistributable Package. As other folks mentioned, you can inspect your application's manifest file to see exactly which version of the C runtime libraries it's linked against.
Before shipping, it's always best to install your product on a clean (i.e., non-developer) virtual machine and run Microsoft's Dependency Walker utility to verify that your application uses the correct C runtime libraries.
you need to ship dll files with you.
you can guess most of them and for the rest you can use a program "Dependency Walker" which shows you dependencies of the executable.
Look at the generated manifest file to see which version of the CRT you need to ship with. It's possible to change which version of the CRT you link to as seen here but it doesn't seem to be recommended.

Resources