Check if a DLL is present in the system
Asked Answered
G

5

19

quick question. I want to find out if a DLL is present in the system where my application is executing.

Is this possible in C#? (in a way that would work on ALL Windows OS?)

For DLL i mean a non-.NET classic dll (a Win32 dll)

(Basically I want to make a check cause I'm using a DLL that may or may not be present on the user system, but I don't want the app to crash without warning when this is not present :P)

Granddaughter answered 18/2, 2010 at 22:6 Comment(2)
Is the goal to not get an error if the file is not present or to find what is present.Ajay
The goal is to know if the dll is not present and show the user a "You are missing the dll xxx.dll. Go update your system".Granddaughter
P
17

Call the LoadLibrary API function:

[DllImport("kernel32", SetLastError=true)]
static extern IntPtr LoadLibrary(string lpFileName);

static bool CheckLibrary(string fileName) {
    return LoadLibrary(fileName) == IntPtr.Zero;
}
Patricio answered 18/2, 2010 at 22:11 Comment(11)
@feal - Beware that this doesn't proof anything other than that the DLL failed to load. There are many reasons, a missing file is just one of them.Affer
That doesn't just check the library, it loads it and keeps it loaded. You have to manually FreeLibrary.Hectic
Well, the library would be loaded anyway ALWAYS by my app (as its used 100% by the app :D), so the freelibrary is unneeded i think.Granddaughter
feal87, just for clarification, how were you binding to the library previously? Were you calling LoadLibrary?Hectic
IMHO the FreeLibrary is needed - otherwise you leak a reference to the library. This might not matter now but in the future, someone's going to think that CheckLibrary has no side effects and it's going to burn you.Woehick
Larry is right, not to mention it'll put noise into your Application Verifier checks. You are using AppVerifier to check for bugs, right?? Right??Centiare
"The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count)." Citation from MSDN, but anyway a freelibrary cost nothing. I'll add it :PGranddaughter
I tried for the fun of it AppVerifier. 0 Error and 2 warning. Both warning are caused by the Intel Graphic Driver. :PGranddaughter
Umm... I think you need to change that to return LoadLibrary(fileName) != IntPtr.Zero... "If the function succeeds, the return value is a handle to the module. If the function fails, the return value is NULL." Edit: I edited it for you.Laryngitis
Now a new headache. Sophos HitmanPro.Alert will flag your software as malware if you attempt to call LoadLibrary from C#.Laryngitis
Keep in mind that LoadLibrary() can fail because one of the DLL dependencies are missing. For example, your.dll may require vcruntime140.dll, and VisualC redistributable is not installed. In that case you won't be able to distinguish the cause of load failure.Disrate
B
6

When using platform invoke calls in .NET, you could use the Marshal.PrelinkAll(Type) method:

Setup tasks provide early initialization and are performed automatically when the target method is invoked. First-time tasks include the following:

Verifying that the platform invoke metadata is correctly formatted.

Verifying that all the managed types are valid parameters of platform invoke functions.

Locating and loading the unmanaged DLL into the process.

Locating the entry point in the process.

As you can see, it performs additional checks other than if the dll exists, like locating the entry points (e.g if SomeMethod() and SomeMethod2() actually exist in the process like in the following code).

using System.Runtime.InteropServices;

public class MY_PINVOKES
{
    [DllImport("some.dll")]
    private static void SomeMethod();

    [DllImport("some.dll")]
    private static void SomeMethod2();
}

Then use a try/catch strategy to perform your check:

try
{
    // MY_PINVOKES class where P/Invokes are
    Marshal.PrelinkAll( typeof( MY_PINVOKES) );
}
catch
{
    // Handle error, DLL or Method may not exist
}
Bashemath answered 9/1, 2019 at 16:15 Comment(2)
This should be the chosen answer.Disrate
This doesn't work for me at all. The method PrelinkAll() doesn't throw if the DLL is missing.Peppery
C
4

Actually it does not throw FileNotFoundException.

Also for that one needs to check in multiple places for path, for the LoadLibrary

There is a standard exception in .net the is derived from TypeLoadException, that is DllNotFoundException.

Best way is to wrap a method/PInvoke call in try..catch and handle the DllNotFoundException since .net will check for application path as well as any other paths set as part of PATH OS Environment variable.

[DllImport("some.dll")]
private static void SomeMethod();

public static void SomeMethodWrapper() {
try {
      SomeMethod();
    } catch (DllNotFoundException) {
    // Handle your logic here
  }
}
Catiline answered 9/7, 2013 at 11:26 Comment(0)
H
1

Call LoadLibrary.

http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx

Hectic answered 18/2, 2010 at 22:10 Comment(1)
Elaborate more on the subject?Granddaughter
K
1

I'm assuming this is a PInvoke call?

If so the easiest way to make this determine if it's present is to make the call and catch the exception that results if the file does not exist.

[DllImport("some.dll")]
private static void SomeMethod();

public static void SomeMethodWrapper() {
  try {
    SomeMethod();
  } catch (DllNotFoundException) {
    // Do Nothing 
  }
}
Kotick answered 18/2, 2010 at 22:10 Comment(1)
Its not a simple single call, the first call may not be the same all the time. I need a check more "higher level"Granddaughter

© 2022 - 2024 — McMap. All rights reserved.