认识非托管动态链接库

一、非托管动态链接库

1、非托管动态链接库(Unmanaged Dynamic Link Library,简称DLL)

是一种包含可执行代码和数据的二进制文件,它被设计为在操作系统级别上执行。与托管代码不同,非托管DLL是使用原生机器代码编写的,并且不依赖于特定的运行时环境(如.NET Framework或.NET Core)。

非托管DLL通常由C、C++或其他低级语言编写,并且可以在多个编程语言和平台上使用。它们提供了对操作系统API、硬件驱动程序和其他系统级功能的访问。

2、使用非托管DLL可以实现以下功能:

(1)访问操作系统级别的功能:

非托管DLL可以直接调用操作系统提供的API,访问底层功能,如文件操作、网络通信、图形处理等。

(2)调用硬件驱动程序:

非托管DLL可以与硬件设备进行交互,如打印机、摄像头、传感器等。

(3)提供性能优势:

由于非托管DLL是使用原生机器代码编写的,它们通常比托管代码执行速度更快,对于对性能要求较高的任务,可以使用非托管DLL来实现。

3、在使用非托管DLL时,需要注意以下几点:

(1)平台兼容性:

非托管DLL是特定于操作系统和硬件平台的,因此需要根据目标平台选择正确的DLL版本。

(2)内存管理:

非托管DLL使用自己的内存管理机制,可能需要手动分配和释放内存,需要小心处理内存泄漏和访问冲突的问题。

(3)安全性:

非托管DLL可以直接访问系统资源,因此需要小心处理安全性问题,避免潜在的漏洞和攻击。

总之,非托管动态链接库是一种使用原生机器代码编写的二进制文件,用于访问操作系统级别的功能和提供性能优势。它们在许多编程语言和平台上都有广泛的应用。

二、user32.dll

1、user32.dll是Windows操作系统中的一个非托管动态链接库(DLL),它包含了许多用户界面相关的函数和功能。

在C#中,我们可以使用P/Invoke机制来访问和调用user32.dll中的函数。通过在C#代码中声明这些函数的签名,并使用 DllImport 特性来指定user32.dll的路径和函数名,我们可以在C#中调用user32.dll中的函数。

这样,我们可以使用user32.dll提供的函数来实现与用户界面相关的操作,如创建和管理窗口、处理鼠标和键盘输入、显示消息框等。user32.dll是Windows操作系统的一部分,因此它在所有安装了Windows的计算机上都可用。

2、在 Windows 系统中,user32.dll 文件通常位于以下目录之一

C:\Windows\System32:这是最常见的 DLL 文件存放目录,包含了许多系统级别的 DLL 文件。

C:\Windows\SysWOW64:这是用于存放 32 位应用程序所需的 32 位 DLL 文件的目录。请注意,即使在 64 位系统上,32 位应用程序仍然使用这个目录来查找其所需的 32 位 DLL 文件。

不同版本目录位置不同。

三、如何调用非托管动态链接库

1、C#中使用非托管动态链接库(DLL),您可以使用平台调用(Platform Invocation Services,简称P/Invoke)机制。下面是使用P/Invoke的一般步骤:

(1)导入DLL:使用 DllImport 特性声明非托管DLL中的函数。在特性中,指定DLL的路径和函数名。

[DllImport("yourDLL.dll")]

public static extern returnType functionName(parameters);

(2)声明函数签名:在C#代码中声明与非托管DLL中函数相对应的函数签名。确保参数类型和返回类型与DLL中的函数匹配。

public static extern returnType functionName(parameters);

(3)调用函数:在C#代码中调用声明的函数。

returnType result = functionName(arguments);

2、注意事项:

  • 非托管DLL的路径应该是绝对路径或者位于系统路径(如Windows\System32)下。

  • 参数和返回类型应该与非托管DLL中函数的定义一致。

  • 非托管DLL中函数的调用约定(calling convention)可能需要进行显式的指定,如 StdCall 或 Cdecl。

需要注意的是,使用非托管DLL需要小心处理内存管理、安全性和平台兼容性等问题。确保正确释放内存、处理异常和错误,并确保在不同的操作系统和体系结构上都能正常工作。

另外,有些非托管DLL可能提供了专门为C#等托管语言编写的托管包装器DLL,这些包装器DLL提供了更方便的面向对象的API,可以更容易地与非托管DLL进行交互。在这种情况下,您可以直接引用这些托管包装器DLL,而不需要使用P/Invoke来调用非托管DLL中的函数。

总结起来,使用P/Invoke机制可以在C#中访问和调用非托管动态链接库中的函数。通过声明函数签名,并使用 DllImport 特性指定DLL的路径和函数名,您可以在C#代码中调用非托管DLL中的函数。

四、实例

1、模拟按下Alt+Tab键

cs 复制代码
        /// <summary>
        ///
        /// </summary>
        /// <param name="bVk">模拟的键</param>
        /// <param name="bScan">保留参数,0</param>
        /// <param name="dwFlags">按键标志,0按下,2释放</param>
        /// <param name="dwExtraInfo">保留,0用(UIntPtr.Zero)表示</param>
        [DllImport("user32.dll")]
        private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

        private void BtnStart_Click(object sender, EventArgs e)
        {
            keybd_event((byte)Keys.Menu, 0, 0, UIntPtr.Zero);//按下alt
            keybd_event((byte)Keys.Tab, 0, 0, UIntPtr.Zero);//按下tab
            keybd_event((byte)Keys.Menu, 0, 2, UIntPtr.Zero);//松开alt
            keybd_event((byte)Keys.Tab, 0, 2, UIntPtr.Zero);//松开tal
        }

2、什么是extern?

extern用于声明一个外部方法。它通常用于与非托管代码(如C/C++)进行交互,以便在C#中调用非托管代码中的函数。

使用extern关键字可以将非托管函数的声明引入到C#代码中,以便在C#中调用该函数。声明外部函数时,需要使用DllImport特性来指定非托管库的名称和其他相关信息。

3、Keys.Menu与Keys.Alt的区别?

两者实则是一个键,在表示单一键时,用Keys.Menu;在表示组合(与Ctrl,Shift)时,用Keys.Alt,此时被视为修饰键。

4、UIntPtr是什么?

UIntPtr是一个结构体,用于表示一个指针或句柄的无符号整数。它可以用来表示指针或句柄的值,而无需关心具体的平台和指针的大小。UIntPtr的大小和指针的大小是平台相关的。在32位系统上,UIntPtr的大小为4字节,在64位系统上,UIntPtr的大小为8字节。

在非托管的DLL中,当需要传递一个空指针或无效句柄时,可以使用UIntPtr.Zero来表示。UIntPtr.Zero是一个UIntPtr类型的静态字段,它的值为0,可以用于表示空指针或无效句柄。

在非托管代码中,通常会使用整数类型(如int或IntPtr)来表示指针或句柄。当需要传递一个空指针或无效句柄时,可以将整数值设置为0。在C#中,可以使用UIntPtr.Zero来表示这个整数值为0的指针或句柄。

五、excel的dll引用

非托管动态链接库是不能直接引用的,但为什么excel的dll是可以引用的?

非托管动态链接库(DLL)是不能直接在C#代码中引用的。C#是一种托管语言,它运行在托管环境中,而非托管DLL是使用其他编程语言(如C++)编写的,并且运行在非托管环境中。要在C#代码中使用非托管DLL中的函数,需要使用DllImport特性和extern关键字来声明外部方法。

然而,有一些特定的非托管DLL,如Excel的DLL(例如"Interop.Excel.dll"),它们是由Microsoft提供的专门用于与Excel进行交互的托管包装器。这些托管包装器DLL是使用C#或其他托管语言编写的,它们封装了与Excel交互所需的COM接口和功能,并提供了更方便的面向对象的API供C#开发人员使用。

因此,当我们在C#项目中引用Excel的DLL时,实际上是引用了这些托管包装器DLL,而不是直接引用非托管DLL。这些托管包装器DLL已经处理了与非托管DLL的交互细节,并提供了更高级别的API,使我们可以更轻松地与Excel进行交互。

总结,虽然非托管DLL一般需要通过P/Invoke机制来访问和调用,但某些特定的非托管DLL,如Excel的DLL,可以通过引用托管包装器DLL来提供更方便的API和交互方式。这样,我们可以直接在C#代码中使用这些托管包装器DLL提供的功能,而不需要手动进行P/Invoke调用。

P/Invoke(Platform Invocation Services):

是一种在.NET平台上调用非托管代码的技术。它允许.NET应用程序使用DllImport属性和相关的DllImport函数来调用C/C++等非托管代码中的函数。

通过P/Invoke,可以在.NET应用程序中直接调用非托管动态链接库(DLL)中的函数。这对于需要访问操作系统API、硬件驱动程序或其他原生代码的情况非常有用。

相关推荐
向宇it3 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
向宇it5 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
坐井观老天9 小时前
在C#中使用资源保存图像和文本和其他数据并在运行时加载
开发语言·c#
pchmi11 小时前
C# OpenCV机器视觉:模板匹配
opencv·c#·机器视觉
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭13 小时前
C#都可以找哪些工作?
开发语言·c#
boligongzhu15 小时前
Dalsa线阵CCD相机使用开发手册
c#
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇23】C#面向对象继承——`as`类型转化和`is`类型检查、向上转型和向下转型、里氏替换原则(LSP)
java·开发语言·unity·c#·游戏引擎·里氏替换原则
sukalot1 天前
windows C#-命名实参和可选实参(下)
windows·c#
小码编匠1 天前
.NET 下 RabbitMQ 队列、死信队列、延时队列及小应用
后端·c#·.net