Click here to Skip to main content
15,884,628 members
Articles / Programming Languages / C#
Technical Blog

Essential tools for debugging and troubleshooting: Dependency Walker aka Depends

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
25 Feb 2013CPOL3 min read 13K   4   2
Essential tools for debugging and troubleshooting.

Introduction

This is the first article of the "Essential tools for debugging and troubleshooting" series. Visit the series main page for more information and to discover other tools.

Dependency Walker

Dependency walker (a.k.a. Depends) is a simple yet powerful tool that you’ll find invaluable if you have to track the native dependencies of your components (EXE or DLL). Dependency Walker can be used for static (without having to run any code) or dynamic analysis (with dependencies tracked while running your code).

I’ll illustrate its usefulness with a from scratch sample. Say you are in the very common situation where you have a native dependency which itself has dependencies. Whatever the technology used you have this situation :

 ________       _________       _________
| CALLER | --> | NATIVE1 | --> | NATIVE2 |
 --------       ---------       ---------

(By the way isn’t it a stunning demonstration of my awesome ASCII art skills?)

When the "native2" dependency is missing, often the root cause remains hidden and you get a generic error message like "Unable to load DLL ‘native1.dll’ : The specified module could not be found" without mentioning "native2".

So you first naively double-check that your "native1.dll" dependency is here and accessible but once you’re convinced "native1.dll" is not the root-cause you realize you definitely need more information to troubleshoot the issue.

Let’s reproduce this situation with a very basic sample and troubleshoot it with Dependency Walker (source code is packaged here : Depends sample source code).

Here is the native2 C source-code:

MC++
__declspec(dllexport) void g()
{
}

and the native1 C code that uses native2 function g:

MC++
extern void g();

__declspec(dllexport) void f()
{
    g();
}

Now is the consumer of native1, a C# application, Test:

C#
using System.Runtime.InteropServices;

class Test
{
    [DllImport("native1.dll")]
    extern static void f();

    static void Main()
    {
        f();
    }
}

So the Test application calls the f function of native1 and f calls itself the g function of native2. As you’ve guessed all this stuff does…nothing.

So let’s build our amazing application that does nothing!

First open a Visual Studio Command Prompt and navigate to the folder containing your source-code files and then follow the guide:

  • we first compile native2:
    >cl /LD native2.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    native2.c
    Microsoft (R) Incremental Linker Version 10.00.40219.01
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:native2.dll
    /dll
    /implib:native2.lib
    native2.obj
       Creating library native2.lib and object native2.exp

    We now have a "native2.dll" DLL and a "native2.lib" exports file.

  • then we compile native1:
    >cl /LD native1.c native2.lib
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    native1.c
    Microsoft (R) Incremental Linker Version 10.00.40219.01
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:native1.dll
    /dll
    /implib:native1.lib
    native1.obj
    native2.lib
       Creating library native1.lib and object native1.exp

    This generates "native1.dll".

  • and finally we compile Test:
    >csc /platform:x86 Test.cs
    Microsoft (R) Visual C# Compiler version 4.0.30319.17929
    for Microsoft (R) .NET Framework 4.5
    Copyright (C) Microsoft Corporation. All rights reserved.

We now have a useless application, Test.exe, that does what it is intended for and we can prove it by running it:

>Test.exe

>

Nothing, no errors, the boss will be happy.

So far so good…

Now let’s play and imagine that the application has been deployed on another environment where native2.dll is missing or is not where it is expected. To simulate this situation delete or rename the native2.dll file an rerun Test.exe:

>Test.exe

Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'native1.dl
l': The specified module could not be found. (Exception from HRESULT: 0x8007007E
)
   at Test.f()
   at Test.Main()

Oops! we’ve broken something, let’s see what Depends have to say about it.

Run the "depends.exe" application you’ve downloaded from the Dependency Walker website. From here open the native1.dll file (you can simply drag-and-drop it from your Windows explorer). You should first see an error popup saying that something is wrong with your DLL:

Depends errors popup

Depends errors popup

So at this point Depends is only telling you something you already knew.

So click OK to be presented with the main interface where you have more information:

Depends UI

Depends UI

Interesting : we now see the root cause : the "native2.dll" file is missing.

From here you can check if the "native2.dll" is on the system; if no install it, if yes check that its folder is correctly referenced in the PATH environment variable.

Conclusion

I hope this quick introduction and demo of Depends have been helpful to you and that you will leverage Depends in your future troubleshooting sessions.

Actually Depends can do more than dependency tracking: for instance in the screenshot you may have noticed that Depends also displays the list of all the exported functions of the DLL (here only "f") which can at times be a very useful information when you don’t understand why you are not able to access (e.g., via DllImport) a function that should be available.

If you have any remarks, questions, suggestions about this article or want to share your experience using Depends please let a comment.

This article was originally posted at http://pragmateek.com/essential-tools-dependency-walker

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer Pragmateek
France (Metropolitan) France (Metropolitan)
To make it short I'm an IT trainer specialized in the .Net ecosystem (framework, C#, WPF, Excel addins...).
(I'm available in France and bordering countries, and I only teach in french.)

I like to learn new things, particularly to understand what happens under the hood, and I do my best to share my humble knowledge with others by direct teaching, by posting articles on my blog (pragmateek.com), or by answering questions on forums.

Comments and Discussions

 
GeneralMy vote of 4 Pin
Luis Gustavo Fernández Batres4-Mar-13 17:06
professionalLuis Gustavo Fernández Batres4-Mar-13 17:06 
GeneralRe: My vote of 4 Pin
Pragmateek4-Mar-13 22:21
professionalPragmateek4-Mar-13 22:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.