Visual Studio 2015 C++ app requires api-ms-win-crt-runtime-l1-1-0.dll on client clients

17

I've built an application with Visual Studio 2015 Community edition. When some of my users try to run it it they receive the following error:

The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing from your computer. Try reinstalling the program to fix this problem.

Clearly this is solved by installing the Update for Universal C Runtime in Windows (KB2999226). I could check for the hotfix during the install script but all of the methods I've found to do this are either too slow or unreliable.

How can I prevent this error from occurring? Can I change my solution so that I don't require this dependency? Am I linking against something I can remove? Can I redistribute the hotfix along with my application?

Edit: In the project properties, the "Target Platform Version" is 8.1 and the "Platform Toolset" is "Visual Studio 2015 (v140)", if that helps at all.

Edit 2: I've tried copying all of the Universal C Runtime Library DLL's to the application directory since Microsoft now allows (but doesn't recommend) local mode installation of the UCRT. There are 41 files in C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x64 and api-ms-win-crt-runtime-l1-1-0.dll is one of them. However, now running the application results in this error:

The application was unable to start correctly (0xc0000142). Click OK to close the application.

I've tried debugging the application with MSVS 2015 but got nowhere. I opened the executable in Dependency Walker and it appears that I'm missing similar DLLs listed in this answer, which says that Dependency Walker is old and this is a red herring.

I tried running the application through Process Monitor (procmon) and there's nothing unusual. The application simply calls "Process Create" on WerFault.exe and then "Thread Exit."

Edit 3: I enabled loader snaps on the executable and got this when running it from cdb, if it helps:

...
00c0:1200 @ 02106250 - LdrpFindOrMapDependency - RETURN: Status: 0x00000000
00c0:1200 @ 02106250 - LdrpFindOrMapDependency - ENTER: DLL name: api-ms-win-core-sysinfo-l1-2-1.dll.
00c0:1200 @ 02106250 - LdrpFindOrMapDependency - INFO: DLL name api-ms-win-core-sysinfo-l1-2-1.dll was redirected to C:\WINDOWS\SYSTEM32\kernelbase.dll by SxS.
00c0:1200 @ 02106250 - LdrpFindOrMapDll - ENTER: DLL name: C:\WINDOWS\SYSTEM32\kernelbase.dll
00c0:1200 @ 02106250 - LdrpResolveDllName - ENTER: DLL name: C:\WINDOWS\SYSTEM32\kernelbase.dll
00c0:1200 @ 02106250 - LdrpResolveDllName - RETURN: Status: 0x00000000
00c0:1200 @ 02106250 - LdrpFindOrMapDll - RETURN: Status: 0x00000000
00c0:1200 @ 02106250 - LdrpFindOrMapDependency - RETURN: Status: 0x00000000
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "RtlSetLastWin32Error" by name
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "RtlLeaveCriticalSection" by name
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "RtlEnterCriticalSection" by name
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "RtlInitializeCriticalSection" by name
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "RtlDeleteCriticalSection" by name
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "RtlQueryPerformanceCounter" by name
00c0:1200 @ 02106250 - LdrpGetProcedureAddress - INFO: Locating procedure "LdrResolveDelayLoadedAPI" by name
00c0:1200 @ 02106250 - LdrpMergeNodes - INFO: Merging a cycle rooted at USER32.dll.
00c0:1200 @ 02106250 - LdrpMergeNodes - INFO: Adding cyclic module GDI32.dll.
(c0.1200): Break instruction exception - code 80000003 (first chance)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll -
ntdll!LdrInitShimEngineDynamic+0x330:
00007ffc`d68732e8 cc              int     3
0:000>
c++
windows
visual-studio
dll
asked on Stack Overflow Jan 28, 2016 by a paid nerd • edited May 23, 2017 by Community

2 Answers

6

You should link statically with the CRT. For a consumer application there are a lot of scenarios which result in particular DLL missing or its configuration botched. I was the installer technical lead for a very popular Windows application (thousands of installs per day) and you would not believe how common misconfigured Windows machines are out there. At the bottom I'll give a short list.

The universal CRT is a good idea but relatively new and it will be a while, (possibly a long while) until it being broken prevents your customers' PC from booting. That should be the threshold: If your customer cannot log in without DLL X then it is ok to depend on it.

Common Weird states:

  • MSI installer in progress : Somehow Windows thinks that there is an installation in progress
  • COM database inconsistent : The HKCU part of the registry is a rough place
  • Missing MSVC crts or pre-release versions in there
  • Pre-release versions of Windows : we guess that pre-release Windows are easier to pirate.
  • Still in sysprep : The OEM forgot to seal the machine configuration.
  • Fonts corrupt: Specially painful if you use DirectWrite
  • Overclocked: eventual bit flips in filesystem buffers equal corrupted files.
answered on Stack Overflow Feb 6, 2016 by AlienRancher
3

I could check for the hotfix

Pretty important to keep in mind that this is not a hotfix. It is a normal update that is automatically delivered through Windows Update. So there's one fact you know, these machines are not being maintained. That's Very Bad News of course and having problems is to be expected.

api-ms-win-crt-runtime-l1-1-0.dll is missing

It is an operating system DLL that is normally supplied along with the operating system install, starting with Win7. That ought to narrow down what's wrong with these machines, they are likely to boot XP. Small odds for Vista. XP is no longer maintained by Microsoft so seeing the update missing is not a coincidence.

the "Target Platform Version" is 8.1 and the "Platform Toolset" is "Visual Studio 2015 (v140)"

That's fine but you need to double-check this in your installer and refuse to install on XP. Targeting XP is still possible, you have to change the Platform Toolset setting to "v140_xp". Not sure if that option is available in the Community edition, it would surprise me if it was.

There are 41 files in ...

Only one counts, ucrtbase.dll. The rest of them are the api-ms-win*.dll files that ought to be present in the Windows install directory. They are included so you can still get it going on XP and Vista, you should deploy these to c:\windows\system32 or c:\windows\syswow64, depending on the bitness. Do note that you documented the x64 directory, verifying that the user has a 64-bit version of Windows is another thing you have to double-check in your installer.

The application was unable to start correctly (0xc0000142).

That is STATUS_DLL_INIT_FAILED, the DllMain() entrypoint of one of the DLLs you have a dependency on returned FALSE. Pretty bad news, not easy to debug and you certainly won't get anywhere trying to tackle this with VS2015 since it won't fail on your machine. You need to turn on loader snaps so the OS loader becomes chatty. Having access to a machine that has this problem is of course mandatory.

Clearly this is solved by installing the Update ...

Yeah, time to cut your losses I'd say. Nobody can reasonably expect your app to work when they intentionally don't maintain their machine or refuse to update it. Verify in your installer that ucrtbase.dll is present and when it is not then just stop the install and tell them to update their machine first.

answered on Stack Overflow Jan 31, 2016 by Hans Passant

User contributions licensed under CC BY-SA 3.0