Using DllImport to Call a Function in .NET

來源:互聯網
上載者:User

Using DllImport to Call a Function in .NET

 

嚴競雄
JingxiongYan@hotmail.com

 

在.NET開發環境中 如果我們需要調用其他非託管庫中的函數 則需要使用DllImportAttribute這個屬性 在MSDN中 這個屬性是被這樣定義的

You can apply this attribute to methods.

The DllImportAttribute attribute provides the information needed to call a function exported from an unmanaged DLL. As a minimum requirement, you must supply the name of the DLL containing the entry point.

You apply this attribute directly to C# and C++ method definitions; however, the Visual Basic compiler emits this attribute when you use the Declare statement. For complex method definitions that include BestFitMapping, CallingConvention, ExactSpelling, PreserveSig, SetLastError, or ThrowOnUnmappableChar fields, you apply this attribute directly to Visual Basic method definitions.

可將該屬性應用於方法,DllImportAttribute 屬性提供對從非託管 DLL 匯出的函數進行調用所必需的資訊,作為最低要求,必須提供包含進入點的 DLL 的名稱。並且,MSDN給了我們一個具體的執行個體,在CSharp中利用DllImport調用User32.dll庫中的MessageBox方法

首先,我們先看一下在Windows XP Pro SP3的SDK中MessageBox方法是如何被定義的

/*
 * MessageBox() Flags
 */
#define MB_OK                       0x00000000L
#define MB_OKCANCEL                 0x00000001L
#define MB_ABORTRETRYIGNORE         0x00000002L
#define MB_YESNOCANCEL              0x00000003L
#define MB_YESNO                    0x00000004L
#define MB_RETRYCANCEL              0x00000005L
#if(WINVER >= 0x0500)
#define MB_CANCELTRYCONTINUE        0x00000006L
#endif /* WINVER >= 0x0500 */

#define MB_ICONHAND                 0x00000010L
#define MB_ICONQUESTION             0x00000020L
#define MB_ICONEXCLAMATION          0x00000030L
#define MB_ICONASTERISK             0x00000040L

#if(WINVER >= 0x0400)
#define MB_USERICON                 0x00000080L
#define MB_ICONWARNING              MB_ICONEXCLAMATION
#define MB_ICONERROR                MB_ICONHAND
#endif /* WINVER >= 0x0400 */

#define MB_ICONINFORMATION          MB_ICONASTERISK
#define MB_ICONSTOP                 MB_ICONHAND

#define MB_DEFBUTTON1               0x00000000L
#define MB_DEFBUTTON2               0x00000100L
#define MB_DEFBUTTON3               0x00000200L
#if(WINVER >= 0x0400)
#define MB_DEFBUTTON4               0x00000300L
#endif /* WINVER >= 0x0400 */

#define MB_APPLMODAL                0x00000000L
#define MB_SYSTEMMODAL              0x00001000L
#define MB_TASKMODAL                0x00002000L
#if(WINVER >= 0x0400)
#define MB_HELP                     0x00004000L // Help Button
#endif /* WINVER >= 0x0400 */

#define MB_NOFOCUS                  0x00008000L
#define MB_SETFOREGROUND            0x00010000L
#define MB_DEFAULT_DESKTOP_ONLY     0x00020000L

#if(WINVER >= 0x0400)
#define MB_TOPMOST                  0x00040000L
#define MB_RIGHT                    0x00080000L
#define MB_RTLREADING               0x00100000L

#endif /* WINVER >= 0x0400 */

#ifdef _WIN32_WINNT
#if (_WIN32_WINNT >= 0x0400)
#define MB_SERVICE_NOTIFICATION          0x00200000L
#else
#define MB_SERVICE_NOTIFICATION          0x00040000L
#endif
#define MB_SERVICE_NOTIFICATION_NT3X     0x00040000L
#endif

#define MB_TYPEMASK                 0x0000000FL
#define MB_ICONMASK                 0x000000F0L
#define MB_DEFMASK                  0x00000F00L
#define MB_MODEMASK                 0x00003000L
#define MB_MISCMASK                 0x0000C000L

WINUSERAPI
int
WINAPI
MessageBoxA(
    __in_opt HWND hWnd,
    __in_opt LPCSTR lpText,
    __in_opt LPCSTR lpCaption,
    __in UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
    __in_opt HWND hWnd,
    __in_opt LPCWSTR lpText,
    __in_opt LPCWSTR lpCaption,
    __in UINT uType);
#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE

#if defined(_M_CEE)
#undef MessageBox
__inline
int
MessageBox(
    HWND hWnd,
    LPCTSTR lpText,
    LPCTSTR lpCaption,
    UINT uType
    )
{
#ifdef UNICODE
    return MessageBoxW(
#else
    return MessageBoxA(
#endif
        hWnd,
    lpText,
    lpCaption,
    uType
        );
}
#endif  /* _M_CEE */

由此可知,MessageBox共有四個參數 我們只需要按照它所定義的類型跟著套用就行了

using System;
using System.Runtime.InteropServices;

class Example
{
    // Use DllImport to import the Win32 MessageBox function.
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

    static void Main()
    {
        // Call the MessageBox function using platform invoke.
        MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);
    }
}

怎麼樣,是不是很簡單呢,清楚了原理,現在我們就自己動手寫一個DllImportAttribute的應用吧 這個程式所需要完成的功能是向系統中添加一個使用者帳號,通常情況下,我們可以使用Netapi32.dll中的NetUserAdd和NetLocalGroupAdd這兩個函數來完成具體的操作,首先我們看下這兩個函數的原型

NET_API_STATUS NET_API_FUNCTION
NetUserAdd (
    IN  LPCWSTR     servername OPTIONAL,
    IN  DWORD      level,
    IN  LPBYTE     buf,
    OUT LPDWORD    parm_err OPTIONAL
    );
/*
................................
省略掉不相關的內容
*/
typedef struct _USER_INFO_1 {
    LPWSTR   usri1_name;
    LPWSTR   usri1_password;
    DWORD    usri1_password_age;
    DWORD    usri1_priv;
    LPWSTR   usri1_home_dir;
    LPWSTR   usri1_comment;
    DWORD    usri1_flags;
    LPWSTR   usri1_script_path;
}USER_INFO_1, *PUSER_INFO_1, *LPUSER_INFO_1;

NET_API_STATUS NET_API_FUNCTION
NetLocalGroupAdd (
    IN  LPCWSTR   servername OPTIONAL,
    IN  DWORD    level,
    IN  LPBYTE   buf,
    OUT LPDWORD  parm_err OPTIONAL
    );

typedef struct _LOCALGROUP_INFO_1 {
    LPWSTR   lgrpi1_name;
    LPWSTR   lgrpi1_comment;
}LOCALGROUP_INFO_1, *PLOCALGROUP_INFO_1, *LPLOCALGROUP_INFO_1;

好了 搞清楚了它的具體結構 現在就可以自己動手開發一個應用了 CSharp中的具體代碼如下

using System.Runtime.InteropServices;
using Microsoft.Win32;
using System;
//Author:嚴競雄
namespace Task
{
    class AddUserApplication
    {
        [DllImport("Netapi32.dll")]
        extern static int NetUserAdd([MarshalAs(UnmanagedType.LPTStr)] string servername, int level, ref USER_INFO_1 buf, int parm_err);
        [DllImport("Netapi32.dll")]
        extern static int NetLocalGroupAdd([MarshalAs(UnmanagedType.LPTStr)] string servername, int level, ref LOCALGROUP_INFO_1 buf, int parm_err);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct USER_INFO_1
        {
            public string user_information_1_name;
            public string user_information_1_password;
            public string user_information_1_password_age;
            public int user_information_1_priv;
            public string user_information_1_home_dir;
            public string comment;
            public int user_information_1_flags;
            public string user_information_1_script_path;
        }
        public struct LOCALGROUP_INFO_1
        {
            [MarshalAs(UnmanagedType.LPWStr)]public string Add_localgroup_1_name;
            [MarshalAs(UnmanagedType.LPWStr)]public string Add_localgroup_1_comment;
        }
        public static void Main()
        {
            if ((Add_a_User_Account())==false )
            {
                Console.Write("Error: Adding User Failed Sorry");
            }
            else
                Add_a_UserAccount_to_LocalGroup();
        }
        //public static void Usage()
        //{
        //Console.Write("------------------------------------");
        //Console.Write("Code BY Delphiscn");
        //Console.Write("Email:Delphiscn@gmail.com");
        //Console.Write("Blog: http://blog.csdn.net/delphiscn");
        //Console.Write("------------------------------------");
        //}
        public  static Boolean  Add_a_User_Account()
        {
            USER_INFO_1 AddUser = new USER_INFO_1();
            AddUser.user_information_1_name = "Delphiscn";
            AddUser.user_information_1_password = "EvilOctal";
            AddUser.user_information_1_priv = 1;
            AddUser.user_information_1_home_dir = null;
            AddUser.comment = "Add a User Named Delphiscn";
            AddUser.user_information_1_script_path = null;
            if (NetUserAdd(null, 1, ref AddUser, 0) != 0)
            {
                Console.Write("Error: Adding User Failed");
                return false;
            }
            return true;
        }
        public static void Add_a_UserAccount_to_LocalGroup()
        {
            LOCALGROUP_INFO_1 AddToGroup= new LOCALGROUP_INFO_1();
            AddToGroup.Add_localgroup_1_name = "Administrators";
            AddToGroup.Add_localgroup_1_comment = "Add a User to the Administrators Group";
            if (NetLocalGroupAdd(null, 1, ref AddToGroup , 0) != 0)
            {
                Console.Write("Adding To the Administrators Group Failed");
            }
        }
    }

}

在Windows XP Pro SP3    VS 2008 SP1   .NET3.5環境下測試通過

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.