четверг, 21 января 2010 г.

Using unmanaged Dll libraries and setting default dll directory for .NET application


Sometimes it's necessary to call Windows API functions or some custom functions from DLL libraries (not assemblies) in .Net applications (C# or VB.net). For example, we have DLL library created in Visual C++ or Delphi. So, how can we call functions in this library?First of all we need add references on this libraries to our project? Using menu "Add references" is not good idea because it works only with .net assemblies. If you try to add reference on this dll library you've got next error message:


To solve this problem you shoud use DllImport attribute in your project. Let's try to call MessageBox API function from user32.dll library by using DllImport attribute.
I will show this example by using C# console application.

Firstly import namespace System.Runtime.InteropServices. And then add attribute DllImport in class declaration with name of dll library. Parameter CallingConvention define default convention for calling unmanaged function with platform invoke.


using System;
using System.Runtime.InteropServices;

namespace test
{
class Program
{
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int MessageBox(System.IntPtr hWnd, String lpText, String lpCaption, System.UInt32 uType);

static void Main(string[] args)
{
MessageBox(System.IntPtr.Zero, "Test", "Text", 0);
}
}
}

After attribute DllImport I declare WinAPI function MessageBox. Prototype of this function you can find in MSDN. It's important to mark all unmanaged dll function with keywords static and extern.

Run this project and you will see standard windows dialog message box.

Now let's consider next situation: for example you have your own dll library and you want to distribute this library with application.

So, there is two ways: you should add this library into root of project or add special folder to project and add file there. Don't forget to mark library as content:

Well, now if you bild your project dll library will copy to output directory. But there is some problem. If you library located in subfolder (for examle, in folder called "Dlls") of your project when you try to call some dll functions you have got error message "Cannot find dll library".

To solve this problem you need to set dll directory path. For this purpose let's try to use WinAPI function SetDllDirectory. This function add directory to the search path used to locate DLLs for your application.

After calling SetDllDirectory, the DLL search path is:
  1. The directory from which the application loaded.
  2. The directory specified by the lpPathName parameter.
  3. The system directory. The name of this directory is System32.
  4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
  5. The Windows directory.
  6. The directories that are listed in the PATH environment variable.
I use this function in Load event of my project.

public partial class MyForm : Form
{
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool SetDllDirectory(String lpPathName);

private void MyForm_Load(object sender, EventArgs e)
{
// Restores the default search order
SetDllDirectory(null);

// Add dll directory path
SetDllDirectory(AppDomain.CurrentDomain.BaseDirectory + "Dlls");

// Some code here
}
}

First line restore default search paths of application and second line add new path for dll directory.
It's very useful to store dll libraries in separate folder. Is help to structure files in project correctly and always find needed library very quickly.

Комментариев нет:

Отправить комментарий