DoNET调用API小识

本文介绍了.NET调用Windows API的基本原理和方法,包括平台调用服务、DllImport特性以及Declare语句的使用。通过示例详细讲解如何在VB.NET中获取文件图标,展示了在.NET Framework下如何与非托管DLL交互,解决特定功能需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DoNET调用API小识:

 Windows API就是Windows系统的API函数简称(Application Program Interface,即:应用程序接口函数),它是Windows操作系统提供给

各种开发基于Windows平台应用软件的开发语言的一些公用的函数,这些函数一般都比较底层,所以当各种开发语言使用自带的函数或类库已无法解

决问题时,调用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

函数的原因。

 3、虽然微软并不提倡在Visual Basic .Net、Visual C#中调用Windows API函数,但由于目前.Net 框架推出时间较短,.Net FrameWork

SDK中提供的类库还并不足以完全替换Windows API函数的所有功能,所以在某些时候,.Net开发语言还是必须要调用Windows API函数。


API运行机制:
一、平台调用、托管DLL、非托管DLL简介
 托管DLL就是能够在公共语言运行库(Common Language Runtime,简称CLR)中能够直接引用的,并且扩展名为“DLL”的文件。具体所指就

是封装各种命名空间所在的DLL文件,如System.dll等。非托管DLL就是平常所的动态链接库等,其中就包括了封装所有Windows API函数的DLL文件。

各种非托管DLL中的函数在公共语言运行库中不能直接被调用,而需要经过.Net框架提供的“平台调用”服务后才可以。

 “平台调用”是.Net框架为Visual Basic .Net、Visual C#等.Net开发语言提供的一种服务,用以在托管代码中引入各种非托管DLL中封装

的函数(其中包括Windows API函数)。“平台调用”依赖于元数据在运行时查找导出函数并封装其参数。图01公共语言运行库利用“平台服务”调

用非托管DLL中的函数的流程图:
 
       在托管代码中使用“平台调用”服务调用非托管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函数。

    下面以一个具体的例子来说明:用VB.NET查看文件中图标的函数及申明Windows API;
 Visual Basic .Net要实现查看文件中的图标,目前只使用.Net FrameWork SDK是无法实现这种功能的,正如前面所说,主要是由于.Net

FrameWork SDK推出的时间较短,其功能还不可能面面俱到。解决问题的关键是正确使用Windows API函数,其中所涉及到的Windows API函数主要有

二个:其一是获得指定文件中的图标数目;其二是从指定文件的指定位置导出图标的Windows句柄。这二个函数都位于“Shell32.dll”文件中,并且

函数的入口点都为“ExtractIcon”。下面是在Visual Basic .Net中分别使用DllImport特征类和“Declare”语句申明这二个Windows API函数的具

体方法。
 (1).使用DllImport特征类来申明Windows API函数:
  下面是在Visual Basic .Net中使用DllImport特征类申明二个Windows API函数的具体示例:
  '函数ExtractIcon,其功能是是从指定文件的指定位置导出图标的Windows句柄。
 < System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
 Public Function _
  ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As   

  System.IntPtr
 End Function
 '函数Icon_Num,其功能是获得指定文件中的图标数目
 < System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
 Public Function _
  Icon_Num ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
 End Function
 在使用DllImport特征类申明Windows API函数时,如果申明的函数名称和函数的入口点相同,则可以在申明Windows API函数时,省略定义 

函数入口点对应的代码,即EntryPoint对象字段对应的代码,这样声明ExtractIcon函数的代码也可以简化为如下所示:

 < System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
 Public Function _
  ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As   

System.IntPtr
  End Function
 (2)、使用“Declare”语句来申明Windows API函数:
 使用“Declare”语句的确比使用DllImport特征类要简单了许多,下面是在Visual      Basic.Net中使用“Declare”语句来声明上述二个

Windows API函数的具体方法:
 
 Declare Auto Function ExtractIcon Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName  

 As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
 '声明ExtractIcon函数

 Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , 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 "Shell32.dll" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal   

 uiIconInd   ex As UInt32 ) As System.IntPtr  

 

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

< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'声明ExtractIcon函数
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , 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 VB.NET查看文件中的图标
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 Color.Transparent
Label Label1 Text 文件名称:
Label2 Text 图标数目:
Label3 Text ""
Label4Text "0"

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

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


图02:【Visual Basic .Net查看文件中的图标】项目的设计界面
. 把Visual Studio .Net当前窗口切换到Form.vb的代码编辑窗口,并用下列代码替换Form1.vb中的Button1组件的Click事件的处理代码,下列代码是在Button1组件的Click事件中处理查看文件中图标的功能,具体如下:

Private Sub Button1_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button1.Click
If OpenFileDialog1.ShowDialog ( ) = DialogResult.OK Then
 '清除组件中的所有项目
 ListView1.Items.Clear ( )
 ImageList1.Images.Clear ( )
 Dim sfName As String = OpenFileDialog1.FileName
 Label3.Text = sfName
 Dim iIcon_Num As Integer = Icon_Num ( IntPtr.Zero , sfName , -1 )
 '显示文件中的图标数目
 Label4.Text = iIcon_Num.ToString ( )
 Dim i As Integer
 For i = 0 To iIcon_Num - 1 Step 1
  '强制实现int到uint类型转换
  Dim j As UInt32
  j = System.Convert.ToUInt32 ( i )
  Dim hIcon As System.IntPtr = ExtractIcon ( IntPtr.Zero , sfName , j )
  '在imageList1组件中加入当然提取的图标
  ImageList1.Images.Add ( Icon.FromHandle ( hIcon ).ToBitmap ( ) )
  '在ListView组件中加入一个项目
  ListView1.Items.Add ( "第" + ( i + 1 ).ToString ( ) + "个图标" )
  '把加入项目的图象索引指向刚才加入图标在imagList1组件中的索引,从而显示图标
  ListView1.Items ( 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函数的组成部分。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值