天天看點

C#中動态調用DLL動态連結庫

本來是想實作控制台程式運作時自動全屏,但是隻找到VC下的實作方法(http://www.vckbase.com/bbs/prime/viewprime.asp?id=347)。

其中要使用兩個未公開的Win32 API函數來存取控制台視窗,這就需要使用動态調用的方法,動态調用中使用的Windows API函數主要有三個,即:Loadlibrary,GetProcAddress和Freelibrary。步驟如下:

1.   Loadlibrary: 裝載指定DLL動态庫

2.   GetProcAddress:獲得函數的入口位址

3.   Freelibrary: 從記憶體中解除安裝動态庫

但是C#中是沒有函數指針,無法直接使用GetProcAddress傳回的入口位址。後來找到資料,其實.NET 2.0新增了Marshal.GetDelegateForFunctionPointer 方法可以滿足這個要求,MSDN裡的解釋是:将非托管函數指針轉換為委托。

後面的事就簡單啦,我把它編成了一個類來友善調用。

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

namespace feiyun0112.cnblogs.com

{

    public class DllInvoke

    {

        Win API#region Win API

        [DllImport("kernel32.dll")]

        private extern static IntPtr LoadLibrary(string path);

        [DllImport("kernel32.dll")]

        private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);

        [DllImport("kernel32.dll")]

        private extern static bool FreeLibrary(IntPtr lib);

        #endregion

        private IntPtr hLib;       

        public DllInvoke(String DLLPath)

        {

            hLib = LoadLibrary(DLLPath);

        }

        ~DllInvoke()

        {

            FreeLibrary(hLib);           

        }

        //将要執行的函數轉換為委托

        public Delegate Invoke (string APIName,Type t) 

        {

            IntPtr api = GetProcAddress(hLib, APIName);

            return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);

        }

    }

}

下面是使用的例子:

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

using feiyun0112.cnblogs.com;

namespace ConsoleApplication1

{

    class Program

    {

        Win API#region Win API

        [DllImport("kernel32.dll")]

        public static extern IntPtr GetStdHandle(int nStdHandle);

        const int STD_OUTPUT_HANDLE = -11;

        #endregion

        public delegate bool SetConsoleDisplayMode(IntPtr hOut, int dwNewMode, out int lpdwOldMode);

        static void Main(string[] args)

        {

            DllInvoke dll = new DllInvoke("kernel32.dll");

            int dwOldMode;

            //标準輸出句柄

            IntPtr hOut = GetStdHandle(STD_OUTPUT_HANDLE);

            //調用Win API,設定螢幕最大化

            SetConsoleDisplayMode s = (SetConsoleDisplayMode)dll.Invoke("SetConsoleDisplayMode", typeof(SetConsoleDisplayMode));

            s(hOut, 1, out dwOldMode);

            Console.WriteLine("********************Full Screen Mode********************");

            Console.ReadLine();

        }

    }

}