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

17,343

Solution 1

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.

Solution 2

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.

Share:
17,343
a paid nerd
Author by

a paid nerd

I'm a professional programmer. I also like riding bicycles. I haven't seen the ResEdit clown in a long time -- or in as anachronistic an environment ever. -- @ruffin 8bde9408bf59382c3194ec7c1bf6afbd837875d7

Updated on July 03, 2022

Comments

  • a paid nerd
    a paid nerd almost 2 years

    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>
    
  • Harry Johnston
    Harry Johnston over 8 years
    OP says the problem still occurs on machines with the VS redistributable. Perhaps the problem isn't that the DLL is missing but that the wrong version is installed? (The application manifest can target a particular version these days, right? Or am I imagining things?)
  • Harry Johnston
    Harry Johnston over 8 years
    Also, I think it should be said that lots of machines (in corporate settings, anyway) don't get non-security updates until the system administrator explicitly determines that a particular update is needed. (Personally I install all mainstream updates on the machines under my control, but most of the rest of the University depends on a WSUS server which is configured to auto-approve security updates only.) So I don't think this scenario is quite as extreme as you're making it out to be.
  • Harry Johnston
    Harry Johnston over 8 years
    (This doesn't mean that asking the user to update isn't the best solution, that sounds right to me. But the error message needs to tell the user which specific update is needed - and for bonus points it could offer to download and install it on the user's behalf, which could be done with the Windows Update client API.)
  • a paid nerd
    a paid nerd over 8 years
    Thank you for the response! This is valuable insight. I should have pointed out, however, that we only support 64-bit Win7 or later and that the installer enforces this. @HarryJohnston Indeed, our current advice to users is to run Windows Update (which fixes the problem), but getting this cryptic DLL error when a consumer application starts is a really bad experience. I haven't found a good way to check for missing deps on install but I'll reconsider that option.
  • a paid nerd
    a paid nerd over 8 years
    "Yeah, time to cut your losses I'd say." -- Heheheh, oh how I would love to. But since this is a public consumer application and most other applications Just Work™, we need to be on the same level. :)
  • Harry Johnston
    Harry Johnston over 8 years
    Perhaps it would work if your build machine didn't have the update in question, or the corresponding update for Visual Studio if distinct? (That is, if the version of the DLL on your build machine matches that on the customer machine?) Probably not a good solution, but it might help narrow down the problem.
  • Neutrino
    Neutrino over 7 years
    Except MS specifiy "strongly recommend against static linking of the Visual C++ libraries, for both performance and serviceability reasons" blogs.msdn.microsoft.com/vcblog/2015/03/03/…
  • Jaromír Adamec
    Jaromír Adamec over 7 years
    Also, if your application is split into exe and one or more dll and an object is created (memory allocated) in a dll and destroyed (memory released) in the exe, the heap gets corrupted, because every module (dll/exe) maintains separate linked C library, therefore also separate heaps. (Not to mention vasting memory by linking the same library several times per each module).