编译器调用API函数的过程

编译器调用API函数的过程,第1张

WindowsAPI函数封装在一些dll文件中,如kernel32dll, gdi32dll, ntdlldll。

每个动态链接库dll文件有一个对应的lib文件,和静态lib将导出声明和实现都放在lib中,编译后所有代码都嵌入到宿主程序有所不同,动态lib相当于一个h文件,是对实现部分(dll文件)的导出部分的声明。链接器使用lib文件来解析对导入的函数/变量的引用,使生成的exe文件包含一个导入表,其中列出必须的DLL和导入的函数/变量以及函数/变量的具体位置。

这样系统在加载exe文件时,会根据导入表的内容同时加载必要的DLL文件,当程序需要使用DLL中的函数/变量时,可查询导入表以找到相应的位置。

这个有API可以的。

通过使用ntdlldll的NtQuerySystemInformation来获得cpu使用率。

//定义内存的信息结构

[StructLayout(LayoutKindSequential)]

public struct MEMORY_INFO

{

public uint dwLength;

public uint dwMemoryLoad; //内存使用率

public uint dwTotalPhys; //物理内存 单位:字节

public uint dwAvailPhys; //可使用的物理内存

public uint dwTotalPageFile; //交换文件

public uint dwAvailPageFile; //尚可交换文件大小

public uint dwTotalVirtual; //总虚拟内存

public uint dwAvailVirtual; //未用虚拟内存

}//定义系统时间的信息结构

[DllImport("kernel32")] public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo);

//获得内存使用率

//调用GlobalMemoryStatus函数获取内存的相关信息

MEMORY_INFO MemInfo;

MemInfo = new MEMORY_INFO();

GlobalMemoryStatus(ref MemInfo);

ConsoleWriteLine("Memory使用率:{0}",MemInfodwMemoryLoad);//内存使用率

为什么不嵌入汇编呢?这样可以事半功倍、

Set dw = CreateObject("DynamicWrapper")

dwRegister "user32DLL", "SetCursorPos","i=ll","f=s","r=l"

a=dwSetCursorPos (100,500)

说明:以上代码保存为vbs文件

设定鼠标位置为(100,500)

评论:这个控件有很多的API函数还是无法使用,例如:无法获取鼠标的坐标(也许是我不会,但是至今没看到这样的代码)

现在我用我所知道的为楼主介绍VBNET的API调用,请楼主浏览一下,看看行不行。

Windows API就是Windows系统的API函数简称(Application Program Interface,即:应用程序接口函数),它是Windows *** 作系统提供给各种开发基于Windows平台应用软件的开发语言的一些公用的函数,这些函数一般都比较底层,所以当各种开发语言使用自带的函数或类库已无法解决问题时,调用Windows API函数往往是一种非常直接、有效的解决方法。但由于在程序中调用Windows API函数一般都很复杂,所以对于程序员来说,是否能够灵活的使用Windows API函数,往往也是其水平高低的一个重要标志。但自从微软推出Net框架以后,各种开发基于Net平台下的程序语言,如Visual Basic Net、Visual C#等却很少使用Windows API函数,并且微软公司也不像以前那样,提倡在这些Net开发语言中使用Windows API函数,其主要的原因如下:

1 Net框架所附带的类库Net FrameWork SDK是一个内容丰富、功能强大的软件开发包,各种Windows API函数所实现的各种功能几乎都可以在这个软件开发包中找到与之对应的部分。

2 微软Visual Basic Net、Visual C#等目的是编写跨平台的应用程序,如果在Visual Basic Net、Visual C#等中使用Windows API函数,这也就注定了编写出的程序只能运行于Windows平台之下,而弱化了NET的跨平台能力。这也就是为什么微软不提倡在Net平台调用Windows API函数的原因。

虽然微软并不提倡在Visual Basic Net、Visual C#中调用Windows API函数,但由于目前Net 框架推出时间较短,Net FrameWork SDK中提供的类库还并不足以完全替换Windows API函数的所有功能,所以在某些时候,Net开发语言还是必须要调用Windows API函数。

一平台调用、托管DLL、非托管DLL简介:

托管DLL就是能够在公共语言运行库(Common Language Runtime,简称CLR)中能够直接引用的,并且扩展名为“DLL”的文件。具体所指就是封装各种命名空间所在的DLL文件,如Systemdll等。非托管DLL就是平常所的动态链接库等,其中就包括了封装所有Windows API函数的DLL文件。各种非托管DLL中的函数在公共语言运行库中不能直接被调用,而需要经过Net框架提供的“平台调用”服务后才可以。

“平台调用”是Net框架为Visual Basic Net、Visual C#等Net开发语言提供的一种服务,用以在托管代码中引入各种非托管DLL中封装的函数(其中包括Windows API函数)。“平台调用”依赖于元数据在运行时查找导出函数并封装其参数。图01公共语言运行库利用“平台服务”调用非托管DLL中的函数的流程图:

图01:“平台服务”的调用非托管函数的流程图

在托管代码中使用“平台调用”服务调用非托管DLL中封装的函数时,“平台服务”将依次执行以下 *** 作:

1. 查找包含该函数所在的DLL文件。

2. 如果找到,则将该DLL文件 加载到内存中。

3. 查找函数在内存中的地址并将其参数推到堆栈上,并封送所需的数据。

4. 将控制权转移给非托管函数。 这样整个函数调用完成。

在Visual Basic Net中使用“平台调用”服务,申明Windows API函数主要有二种具体的实现方法:

1. 使用DllImport特征类来申明Windows API函数。

2. 使用“Declare”语句来申明Windows API函数。

这二种方法虽有异曲同工之效,但在繁简上却有很大差异,第一种方法申明过程比较复杂,很容易在申明Windows API函数时出错,所以并不提倡。而第二种方法相对简单,并且又保存了以前Visual Basic中的很多语法,所以在平常时大都使用这种方法来申明Windows API函数。

二.VBNet查看文件中图标的函数及申明Windows API的方法:

Visual Basic Net要实现查看文件中的图标,目前只使用Net FrameWork SDK是无法实现这种功能的,正如前面所说,主要是由于Net FrameWork SDK推出的时间较短,其功能还不可能面面俱到。解决问题的关键是正确使用Windows API函数,其中所涉及到的Windows API函数主要有二个:其一是获得指定文件中的图标数目;其二是从指定文件的指定位置导出图标的Windows句柄。这二个函数都位于“Shell32dll”文件中,并且函数的入口点都为“ExtractIcon”。下面是在Visual Basic Net中分别使用DllImport特征类和“Declare”语句申明这二个Windows API函数的具体方法。

(1)使用DllImport特征类来申明Windows API函数:

下面是在Visual Basic Net中使用DllImport特征类申明二个Windows API函数的具体示例:

'函数ExtractIcon,其功能是是从指定文件的指定位置导出图标的Windows句柄。

< SystemRuntimeInteropServicesDllImport ( "Shell32dll" , EntryPoint := "ExtractIcon" ) > _

Public Function _

ExtractIcon ( ByVal src As SystemIntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As SystemIntPtr

End Function

'函数Icon_Num,其功能是获得指定文件中的图标数目

< SystemRuntimeInteropServicesDllImport ( "Shell32dll" , EntryPoint := "ExtractIcon" ) > _

Public Function _

Icon_Num ( ByVal src As SystemIntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer

End Function

在使用DllImport特征类申明Windows API函数时,如果申明的函数名称和函数的入口点相同,则可以在申明Windows API函数时,省略定义函数入口点对应的代码,即EntryPoint对象字段对应的代码,这样声明ExtractIcon函数的代码也可以简化为如下所示:

< SystemRuntimeInteropServicesDllImport ( "Shell32dll" ) > _

Public Function _

ExtractIcon ( ByVal src As SystemIntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As SystemIntPtr

End Function

(2)使用“Declare”语句来申明Windows API函数:

使用“Declare”语句的确比使用DllImport特征类要简单了许多,下面是在Visual Basic Net中使用“Declare”语句来声明上述二个Windows API函数的具体方法:

Declare Auto Function ExtractIcon Lib "Shell32dll" Alias "ExtractIcon" ( ByVal src As SystemIntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As SystemIntPtr

'声明ExtractIcon函数

Declare Auto Function Icon_Num Lib "Shell32dll" Alias "ExtractIcon" ( ByVal src As SystemIntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer

'声明Icon_Num函数

在Visual Basic Net中声明Windows API函数时,“Declare”语句中Alias关键字的作用相当于使用DllImport特征类中的EntryPoint对象字段。同样在使用“Declare”语句声明Windows API函数时,如果声明的函数和函数的入口点相同,也可以省略Alias关键字对应的代码,所以ExtractIcon函数也可以简化为如下:

Declare Auto Function ExtractIcon Lib "Shell32dll" ( ByVal src As SystemIntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As SystemIntPtr

下面就结合一个示例的编写过程来掌握的这二个Windows API函数的具体使用方法,这个示例的作用就是读取指定文件中的图标数目,并显示文件中的图标。

三.本文中程序的编写、调试和运行环境:

(1)视窗2000高级服务器版。

(2)Visual Studio Net 2003企业结构设计版,Net FrameWork SDK版本号4322。

四.Visual Basic Net读取文件中的图标的实现步骤:

下面介绍的示例,其功能读取指定文件中包含的图标数目,并把这些图标全部显示出来。下面是这个示例的实现步骤:

1 启动Visual Studio Net。

2 选择菜单文件|新建|项目后,d出新建项目对话框。

3 将项目类型设置为Visual Basic项目。

4 将模板设置为Windows应用程序。

5 在名称文本框中输入Visual Basic Net查看文件中的图标。

6 在位置的文本框中输入E:\VSNET项目,然后单击确定按钮,这样在E:\VSNET项目目录中就产生了名称为Visual Basic Net查看文件中的图标文件夹,里面存放着Visual Basic Net查看文件中的图标项目的所有文件。具体如图02所示:

图02:Visual Basic Net查看文件中的图标项目的新建项目对话框

7 选择菜单项目|添加新项,在d出的对话框中的模板设置为模块,名称文本框设置为Module1vb后。单击打开按钮,则在项目中增加了一个模板文件,名称为Module1vb。

8 把Visual Stuido Net的当前窗口切换到Module1vb的代码编辑窗口,并在其Module1的代码区中添加下列代码,下列代码是用二种方式声明二个Windows API函数:

< SystemRuntimeInteropServicesDllImport ( "Shell32dll" ) > _

Public Function _

ExtractIcon ( ByVal src As SystemIntPtr , ByVal strFileName As String , ByVal uiIconIndex As UInt32 ) As SystemIntPtr

End Function

'声明ExtractIcon函数

Declare Auto Function Icon_Num Lib "Shell32dll" Alias "ExtractIcon" ( ByVal src As SystemIntPtr , ByVal strFileName As String , ByVal uiIconIndex As Integer ) As Integer

9 把Visual Studio Net的当前窗口切换到Form1窗体的设计查看,并从工具箱中的Windows窗体选项卡中拖入下列组件到Form1窗体:

四个Label组件,其中二个用以显示提示信息,另外二个分别用以显示选择的文件名称和这个文件中包含的图标数目。

一个ListView组件,利用其显示大图标的属性用以显示选定文件中的图标。

一个OpenFileDialog组件,用以选择要查看图标的文件名称。

一个ImageList组件,它起的是桥梁的作用,首先把从文件中导出的图标存放到这里,然后再提供ListView组件显示出来。

一个Button组件。

10 按照表01中数值来设定设定组件的主要属性:

组件类型 组件名称 属性 设置结果

Form Form1 Text VBNET查看文件中的图标

Form1 MaximizeBox False

Form1 MinimizeBox False

Form1 FormBorderStyle FixedSingle

ListView ListView1 ImageList1 LargeImageList

ListView1 MultiSelect False

ListView1 Size Size ( 380 , 208 )

Button Button1 Text 选择文件

Button1 FlatStyle Flat

ImageList ImageList1 Size Size ( 32 , 32 )

ImageList1 TransparentColor ColorTransparent

Label Label1 Text 文件名称:

Label2 Text 图标数目:

Label3 Text ""

Label4 Text "0"

表01:Visual Basic Net查看文件中的图标项目窗体中各组件的主要属性设定数值表

并按照图02中各组件的位置、大小和排列方式来调整窗体中各个组件:

图02:Visual Basic Net查看文件中的图标项目的设计界面

11 把Visual Studio Net当前窗口切换到Formvb的代码编辑窗口,并用下列代码替换Form1vb中的Button1组件的Click事件的处理代码,下列代码是在Button1组件的Click事件中处理查看文件中图标的功能,具体如下:

Private Sub Button1_Click ( ByVal sender As SystemObject , ByVal e As SystemEventArgs ) Handles Button1Click

If OpenFileDialog1ShowDialog ( ) = DialogResultOK Then

'清除组件中的所有项目

ListView1ItemsClear ( )

ImageList1ImagesClear ( )

Dim sfName As String = OpenFileDialog1FileName

Label3Text = sfName

Dim iIcon_Num As Integer = Icon_Num ( IntPtrZero , sfName , -1 )

'显示文件中的图标数目

Label4Text = iIcon_NumToString ( )

Dim i As Integer

For i = 0 To iIcon_Num - 1 Step 1

'强制实现int到uint类型转换

Dim j As UInt32

j = SystemConvertToUInt32 ( i )

Dim hIcon As SystemIntPtr = ExtractIcon ( IntPtrZero , sfName , j )

'在imageList1组件中加入当然提取的图标

ImageList1ImagesAdd ( IconFromHandle ( hIcon )ToBitmap ( ) )

'在ListView组件中加入一个项目

ListView1ItemsAdd ( "第" + ( i + 1 )ToString ( ) + "个图标" )

'把加入项目的图象索引指向刚才加入图标在imagList1组件中的索引,从而显示图标

ListView1Items ( i )ImageIndex = i

Next i

End If

End Sub

12 至此,在上述步骤都正确执行后,Visual Basic Net查看文件中的图标项目的全部工作就完成了。单击快捷键F5就可以运行程序,此时单击选择文件按钮选择文件后,程序就能够读取这个文件中的图标及其数目,并显示出来了。具体如图03所示:

图03:Visual Basic Net查看文件中的图标项目的运行界面

五.总结:

解决Visual Basic Net查看文件中的图标的关键并非是使用Net框架中提供的类库,而是使用Windows的API函数。虽然这与利用Visual Basic Net开发跨平台程序的初衷相违背,但的确不失为一种解决问题的方法。有些时候通过Windows API函数能够快捷、方便的解决实际问题,而这往往是只使用Net FrameWork SDK所望尘莫及的,但随着Net FrameWork SDK内容的不断丰富,各种新的组成部分和新的功能不断加入,可以预见的是,在未来的Net FrameWork SDK中必将拥有可以替换本文中介绍的二个Windows API函数的组成部分。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/12180037.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存