API函数是构筑Windows应用程序的基石,是Windows编程的必备利器。每一种Windows应用程序开发工具都提供了间接或直接调用了Windows API函数的方法,或者是调用Windows API函数的接口,也就是说具备调用动态连接库的能力。Visual C#和其它开发工具一样也能够调用动态链接库的API函数。本文中笔者就结合实例向大家介绍在Visual C#中如何调用各种返回值的API,该实例就是一个通过API函数调用获取系统信息的程序。

  在Visual C#中调用API的基本过程:

  首先,在调用API之前,你必须先导入System.Runtime.InteropServices这个名称空间。该名称空间包含了在Visual C#中调用API的一些必要集合,具体的方法如下:

using System.Runtime.InteropServices;

  在导入了名称空间后,我们要声明在程序中所要用到的API函数。我们的程序主要是获取系统的相关信息,所以用到的API函数都是返回系统信息的。先给出在Visual C#中声明API的方法:

[DllImport("kernel32")]
public static extern void GetWindowsDirectory(StringBuilder WinDir,int count);

  其中,"DllImport"属性用来从不可控代码中调用一个方法,它指定了DLL的位置,该DLL中包含调用的外部方法;"kernel32"设定了类库名;"public"指明函数的访问类型为公有的;"static"修饰符声明一个静态元素,而该元素属于类型本身而不是指定的对象;"extern"表示该方法将在工程外部执行,同时使用DllImport导入的方法必须使用"extern"修饰符;最后GetWindowsDirectory函数包含了两个参数,一个为StringBuilder类型的,另一个为int类型的,该方法返回的内容存在于StringBuilder类型的参数中。同时,因为我们在这里使用到了StringBuilder类,所以在程序的开始处,我们还得添加System.Text这个名称空间,方法同上。

  其他几个API函数的声明如下:

[DllImport("kernel32")]
public static extern void GetSystemDirectory(StringBuilder SysDir,int count); [DllImport("kernel32")]
public static extern void GetSystemInfo(ref CPU_INFO cpuinfo); [DllImport("kernel32")]
public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo); [DllImport("kernel32")]
public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo);

  以上几个API的作用分别是获取系统路径,获得CPU相关信息,获得内存的相关信息,获得系统时间等。
在声明完所有的API函数后,我们发现后三个函数分别用到了CPU_INFO、MEMORY_INFO、SYSTEMTIME_INFO等结构,这些结构并非是.Net内部的,它们从何而来?其实,我们在用到以上API调用时均需用到以上结构,我们将函数调用获得的信息存放在以上的结构体中,最后返回给程序输出。这些结构体比较复杂,但是如果开发者能够熟练运用,那么整个API世界将尽在开发者的掌握之中。以下就是上述结构体的声明:

//定义以下各结构
//定义CPU的信息结构
[StructLayout(LayoutKind.Sequential)]
public struct CPU_INFO
{
public uint dwOemId;
public uint dwPageSize;
public uint lpMinimumApplicationAddress;
public uint lpMaximumApplicationAddress;
public uint dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public uint dwProcessorLevel;
public uint dwProcessorRevision;
} //定义内存的信息结构
[StructLayout(LayoutKind.Sequential)]
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;
} //定义系统时间的信息结构
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME_INFO
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}

  结构体定义的主体部分和C++中的没多大差别,具体每个结构体内部成员的定义可参考联机帮助中的SDK文档。同时,我们还发现在每个结构体定义的上面都有一句用中括号括起来的说明性文字。这些说明都是有关结构体成员的布局的,共有三种选项,分别说明如下:

  LayoutKind.Automatic:为了提高效率允许运行态对类型成员重新排序。

    注意:永远不要使用这个选项来调用不受管辖的动态链接库函数。

  LayoutKind.Explicit:对每个域按照FieldOffset属性对类型成员排序

  LayoutKind.Sequential:对出现在受管辖类型定义地方的不受管辖内存中的类型成员进行排序。

  在上面的程序中,为了方便起见我们都用到了第三种方式。

所有的API函数以及相关的结构体声明完毕后,我们就运用这些API来实现我们的程序功能――获取系统的相关信息。

  界面可按如下方式布置,不过有兴趣的读者自然可以发挥自己的想象,将界面布局做得更好。

 

  简单的界面布置好后,我们添加一个按钮("获取信息"按钮)的消息处理函数如下:

private void GetInfo_Click(object sender, System.EventArgs e)
{
//调用GetWindowsDirectory和GetSystemDirectory函数分别取得Windows路径和系统路径
const int nChars = ;
StringBuilder Buff = new StringBuilder(nChars);
GetWindowsDirectory(Buff,nChars);
WindowsDirectory.Text = "Windows路径:"+Buff.ToString();
GetSystemDirectory(Buff,nChars);
SystemDirectory.Text = "系统路径:"+Buff.ToString(); //调用GetSystemInfo函数获取CPU的相关信息
CPU_INFO CpuInfo;
CpuInfo = new CPU_INFO();
GetSystemInfo(ref CpuInfo);
NumberOfProcessors.Text = "本计算机中有"+CpuInfo.dwNumberOfProcessors.ToString()+"个CPU";
ProcessorType.Text = "CPU的类型为"+CpuInfo.dwProcessorType.ToString();
ProcessorLevel.Text = "CPU等级为"+CpuInfo.dwProcessorLevel.ToString();
OemId.Text = "CPU的OEM ID为"+CpuInfo.dwOemId.ToString();
PageSize.Text = "CPU中的页面大小为"+CpuInfo.dwPageSize.ToString(); //调用GlobalMemoryStatus函数获取内存的相关信息
MEMORY_INFO MemInfo;
MemInfo = new MEMORY_INFO();
GlobalMemoryStatus(ref MemInfo);
MemoryLoad.Text = MemInfo.dwMemoryLoad.ToString()+"%的内存正在使用";
TotalPhys.Text = "物理内存共有"+MemInfo.dwTotalPhys.ToString()+"字节";
AvailPhys.Text = "可使用的物理内存有"+MemInfo.dwAvailPhys.ToString()+"字节";
TotalPageFile.Text = "交换文件总大小为"+MemInfo.dwTotalPageFile.ToString()+"字节";
AvailPageFile.Text = "尚可交换文件大小为"+MemInfo.dwAvailPageFile.ToString()+"字节";
TotalVirtual.Text = "总虚拟内存有"+MemInfo.dwTotalVirtual.ToString()+"字节";
AvailVirtual.Text = "未用虚拟内存有"+MemInfo.dwAvailVirtual.ToString()+"字节"; //调用GetSystemTime函数获取系统时间信息
SYSTEMTIME_INFO StInfo;
StInfo = new SYSTEMTIME_INFO();
GetSystemTime(ref StInfo);
Date.Text = StInfo.wYear.ToString()+"年"+StInfo.wMonth.ToString()+"月"+StInfo.wDay.ToString()+"日";
Time.Text = (StInfo.wHour+).ToString()+"点"+StInfo.wMinute.ToString()+"分"+StInfo.wSecond.ToString()+"秒";
}

在上面的消息处理函数中,我们运用了在程序开始处声明的各个API函数获取了系统的相关信息,并最终在界面上以文本标签的方式显示结果。各个文本标签的命名方式可以参见文后附带的源代码,此处暂略。
最后,运行程序如下:

C#API函数的更多相关文章

  1. Windows API 函数列表 附帮助手册

    所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...

  2. C#中可直接调用WIN32的API函数--USER32.DLL

    Win32的API函数可以直接在C#中直接调用,在做WinForm时还是很有帮助的.有时候直接调用Win32的API,可以很高效的实现想要的效果. using System; using System ...

  3. Appium常用的API函数

    在学习应用一个框架之前,应该了解一下这个框架的整体结构或是相应的API函数.这篇文章还不错:http://blog.sina.com.cn/s/blog_68f262210102vzf9.html,就 ...

  4. mfc 调用Windows的API函数实现同步异步串口通信(源码)

    在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...

  5. C#调用Windows API函数截图

    界面如下: 下面放了一个PictureBox 首先是声明函数: //这里是调用 Windows API函数来进行截图 //首先导入库文件 [System.Runtime.InteropServices ...

  6. C#中导入Win32 API函数

    C#中导入Win32 API的方法: 1.引用命名空间 using System.Net.Security; using System.Runtime.InteropServices; 2. [Dll ...

  7. 初识API函数

    我之前是一个只会编写数值计算的程序的OIer,但我并不甘于这种现状,于是我编写了我的第一个使用API函数的C++程序,开发平台是VS2012: // ConsoleApplication.cpp : ...

  8. Linux 编程中的API函数和系统调用的关系【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...

  9. [转]SQLITE3 C语言接口 API 函数简介

    SQLITE3 C语言接口 API 函数简介 说明:本说明文档属作者从接触 SQLite 开始认识的 API 函数的使用方法, 由本人翻译, 不断更新. /* 2012-05-25 */ int sq ...

  10. 替换应用程序exe图标,主要使用BeginUpdateResource,UpdateResource API函数

    替换应用程序exe图标,主要使用的API函数是BeginUpdateResource(),UpdateResource(),EndUpdateResource()来使用自定义的ico文件类替换exe程 ...

随机推荐

  1. Blue Jeans---poj3080(kmp+暴力求子串)

    题目链接:http://poj.org/problem?id=3080 题意就是求n个长度为60的串中求最长公共子序列(长度>=3):如果有多个输出字典序最小的: 我们可以暴力求出第一个串的所有 ...

  2. C++ 带有通配符*与?的字符串匹配

    题目:两个字符串,一个是普通字符串,另一个含有*和?通配符,*代表零个到多个任意字符,?代表一个任意字符,通配符可能多次出现.写一个算法,比较两个字符串是否相等. 发现许多公司笔试面试都有这道题目,于 ...

  3. 为什么说”人生苦短,我用python“?

    本文不扯什么大道理,只是先介绍Python的背景,然后从实用的角度出发举一两个真实栗子. ​ 首先要想了解要一门语言的好坏,或者为什么招程序员喜欢(卧槽,原来程序员喜欢不是女朋友?)我们的先从语言的产 ...

  4. 010-Hadoop Hive sql语法详解5-HiveQL与SQL区别

    1.Hive不支持等值连接 •SQL中对两表内联可以写成:•select * from dual a,dual b where a.key = b.key;•Hive中应为•select * from ...

  5. mysql监控优化(一)连接数和缓存

    一.mysql的连接数 MYSQL数据库安装完成后,默认最大连接数是100,一般流量稍微大一点的论坛或网站这个连接数是远远不够的,连接数少的话,在大并发下连接数会不够用,会有很多线程在等待其他连接释放 ...

  6. 20165324《Java程序设计》第四周

    学号 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 第五章:子类与继承 子类的定义:class 子类名 extends 父类名 { ... } 子类继承性: ...

  7. JS:parseInt("08")或parseInt("09")转换返回0的原因

    一.parseInt用法 parseInt(s); parseInt(s,radix) 二.第一个方式不再多说,第二个方式,radix是s所基于的进制.范围为2-36(不在此范围函数将返回NaN). ...

  8. Linux系统——账号管理

    用户账号管理 分类: 超级用户 root uid=0 gid=0 权限最大 普通用户 uid=>500 ,一般权限的系统管理 程序用户 1=<uid,为了提升系统安全性,支持所对应服务对系 ...

  9. Mac下的Mysql无法登陆的问题

    以下是还原root权限和更改root密码的最便捷方法. 1:装mysql workbench .可视化界面直接操作. 2:苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭my ...

  10. SQL Server排名函数与排名开窗函数

    什么是排名函数?说实话我也不甚清楚,我知道 order by 是排序用的,那么什么又是排名函数呢? 接下来看几个示例就明白了. 首先建立一个表,随便插入一些数据. ROW_NUMBER 函数:直接排序 ...