-->

CreateProcess STATUS_DLL_NOT_FOUND - which dll?

2020-08-13 05:41发布

问题:

I have a process which calls CreateProcess. It appears that CreateProcess returns nonzero indicating success. However, the HANDLE to the process then gets immediately set, indicating the process has exited. When I call GetExitCodeProcess, STATUS_DLL_NOT_FOUND is then returned.

I understand that a DLL is missing. I even know exactly which one. However, what I don't understand is how to figure that out programmatically.

I noticed that Windows will present a dialog saying that the process failed to start because it couldn't find the specified DLL (screenshot: http://www.mediafire.com/view/?kd9ddq0e2dlvlb9 ). In the dialog, Windows specifies which DLL is missing. However, I find no way to get that information myself programmatically.

If a process fails to start and would return STATUS_DLL_NOT_FOUND, how do I programmatically retrieve the library name to which the target process was linked which couldn't be found? That way I can automatically record in an error report what DLL appears to be missing or corrupt in a given installation.

回答1:

CreateProcess returns 0 indicating success.

CreateProcess() returns a BOOL, where 0 is FALSE, aka failure not success.

If a process fails to start and would return STATUS_DLL_NOT_FOUND, how do I programmatically retrieve the library name to which the target process was linked which couldn't be found?

Unfortunately, there is no API for that. Your only option would be to manually access and enumerate the executable's IMPORTS table to find out what DLLs it uses, and then recursively access and enumerate their IMPORTS tables, manually checking every DLL reference you find to see whether that DLL file exists on the OS's search path or not.



回答2:

If the dll is statically linked you can walk the iat and see if the dll exists. If the dll is dynamically loaded then starting the process suspended and hooking LoadLibrary (or instead of hooking emulate a debugger) is the only way I see.



回答3:

The best way is to use loader snaps. Basically you use gflags.exe (which is included with windbg) to enable loader snaps; then, run the process with the debugger attached. Loader snaps will enable the loader to print out dbg messages of the process and it will print the failures.

gflags.exe -i yourcode.exe +sls
windbg yourcode.exe

I know this is not a "programmatic" way to find out the problem, but what the loader does is complicated, and you don't really want to be redoing its logic to find the failure. That is why loader snaps were invented.



回答4:

The very hard way would be: Parsing the .EXE and .DLL files and create the dependency tree of .DLL files.

I don't think there is a way to get a list of DLL files that are missing: When Windows finds one missing DLL file it stops loading so if one DLL file is missing you won't find out if more DLL files are missing.

Another problem you could have is that old DLL versions could have missing "exports" (functions). This is even harder to detect than the dependency tree.



回答5:

Just since this is somehow the top stackoverflow result on Google for "STATUS_DLL_NOT_FOUND". How to trace and solve any random occurence:

Download SysInternals procmon64.exe (or just the entire set). After startup immediately hit the looking glass 'Stop capture' button (Ctrl+E). And 'Clear' (Ctrl+X).

Set filters for:

  • 'Process name' is to whatever the mentioned process name was (for me it was 'build-script-build.exe') [Add]
  • 'Result' is not 'SUCCESS' [Add]
  • 'Path' ends with '.dll' [Add] [OK]

Start capture again (Ctrl+E).

Run the thing that had a problem again (for me: build cargo). Google for the last listed DLL file.

For me that was VCRUNTIME140.dll, so I installed the VC++ 2015 to 2019 redistributable.

ProcMon is kind of like unix strace.