`
lovnet
  • 浏览: 6692116 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

Using DllImport to Call a Function in .NET

阅读更多

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环境下测试通过

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics