When you try to run a program on Windows, and the loader can't find all of the required DLLs, the default behavior is to pop up a dialog box that describes the problem, including both the name of the program and the name of (one of the) missing DLLs. The process then hangs until someone clicks OK, and then exits with an error code. Here's an example of this dialog box:
Now suppose you're scripting some automated process that might fail for this reason, e.g. running CI tests after installation, where part of the point is to make sure the installer installs all the DLLs. You don't want your build workers to hang waiting for someone to click on a dialog box that's being displayed on a monitor that the computer physically does not have because it's in a server rack somewhere. You want the test cycle to stop immediately and the details to get written to the log.
Your build driver can disable this dialog box for itself and all its child processes (assuming nobody uses CREATE_DEFAULT_ERROR_MODE
) by calling SetErrorMode
:
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
hProc = CreateProcess(...);
However, this only solves half of the problem. The offending process will terminate with an exit status of 0xC0000135
(STATUS_DLL_NOT_FOUND
), but the name of the problem executable and the name of the missing DLL are not reported anywhere that I can find it.
So here's the actual question: From code running in the build driver, how do I get the name of the problem executable and the name of the missing DLL, so that I can write them to my CI build logs? Anything goes, except that the code of the problem executable itself and its DLLs cannot be modified (because this is supposed to be a general solution) and an approach that does not require elevated privileges is strongly preferred.
(This is a follow-up question for Suppress "The program can't start because X.dll is missing" error popup . I've been vaguely meaning to write it for years now.)