示例如下:
<Script runat=server>
[DllImport("g:\\程序\\qq123.dll")]
public static extern int LogoffEsm ();
void Page_Load(){
int iOut = LogoffEsm();
lbl.Text = iOut+ "<br>" ;
}</spript>lbl显示给我-1。肯定是不正确的。有人在asp.net里调用过API吗?介绍一下经验呀。提供API给我的人只能对我说一个字:晕。API不是他写的,提供说明文档里没有-1的参数说明。估计写API的人没想到有人会这样用他的API。
<Script runat=server>
[DllImport("g:\\程序\\qq123.dll")]
public static extern int LogoffEsm ();
void Page_Load(){
int iOut = LogoffEsm();
lbl.Text = iOut+ "<br>" ;
}</spript>lbl显示给我-1。肯定是不正确的。有人在asp.net里调用过API吗?介绍一下经验呀。提供API给我的人只能对我说一个字:晕。API不是他写的,提供说明文档里没有-1的参数说明。估计写API的人没想到有人会这样用他的API。
首先,在调用API之前,你必须先导入System.Runtime.InteropServices这个名称空间。该名称空间包含了在Visual C#中调用API的一些必要集合,具体的方法如下: <; ,^Dr]
using System.Runtime.InteropServices; WK./Qc`
在导入了名称空间后,我们要声明在程序中所要用到的API函数。我们的程序主要是获取系统的相关信息,所以用到的API函数都是返回系统信息的。先给出在Visual C#中声明API的方法: G].$l'^3[
[DllImport("kernel32")] >UuD|f Lmi
public static extern void GetWindowsDirectory(StringBuilder WinDir,int count); hfqO!EZv
~.U+3u`R
其中,"DllImport"属性用来从不可控代码中调用一个方法,它指定了DLL的位置,该DLL中包含调用的外部方法;"kernel32"设定了类库名;"public"指明函数的访问类型为公有的;"static"修饰符声明一个静态元素,而该元素属于类型本身而不是指定的对象;"extern"表示该方法将在工程外部执行,同时使用DllImport导入的方法必须使用"extern"修饰符;最后GetWindowsDirectory函数包含了两个参数,一个为StringBuilder类型的,另一个为int类型的,该方法返回的内容存在于StringBuilder类型的参数中。同时,因为我们在这里使用到了StringBuilder类,所以在程序的开始处,我们还得添加System.Text这个名称空间,方法同上。 f e#(8P2O
其他几个API函数的声明如下: _KLzs!
[DllImport("kernel32")] gPp6,Y1-Z
public static extern void GetSystemDirectory(StringBuilder SysDir,int count); Rih,V2+}V
[DllImport("kernel32")] V#8R4d1
public static extern void GetSystemInfo(ref CPU_INFO cpuinfo); VL '][L
[DllImport("kernel32")] j5C-nmv]
public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo); QnTqxQn
[DllImport("kernel32")] =Y=F@V
public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo); $#(G**
DU+M|t&gUa
以上几个API的作用分别是获取系统路径,获得CPU相关信息,获得内存的相关信息,获得系统时间等。 G4$lj%VN
在声明完所有的API函数后,我们发现后三个函数分别用到了CPU_INFO、MEMORY_INFO、SYSTEMTIME_INFO等结构,这些结构并非是.Net内部的,它们从何而来?其实,我们在用到以上API调用时均需用到以上结构,我们将函数调用获得的信息存放在以上的结构体中,最后返回给程序输出。这些结构体比较复杂,但是如果开发者能够熟练运用,那么整个API世界将尽在开发者的掌握之中。以下就是上述结构体的声明: QqP,-%
//定义以下各结构 DhYW3"`
//定义CPU的信息结构 `TIyc&$
[StructLayout(LayoutKind.Sequential)] O(B+~_
public struct CPU_INFO p$9RJ4zN<
{ 0W5 VzTB
public uint dwOemId; *]ffw\M
public uint dwPageSize; \@{k Q; 5
public uint lpMinimumApplicationAddress; 9]vtpW;
public uint lpMaximumApplicationAddress; =H9qS35mQ
public uint dwActiveProcessorMask; D KGC l@
public uint dwNumberOfProcessors; &ibNca 3/
public uint dwProcessorType; |,),-q2
public uint dwAllocationGranularity; =_Z}Q2#i
public uint dwProcessorLevel; \.c pD
public uint dwProcessorRevision; 9 s6SX6C
} db 3aX4J
//定义内存的信息结构 1OszFMB
[StructLayout(LayoutKind.Sequential)] GjB%0hx 'V
public struct MEMORY_INFO &4'z18 e
{ ?BA7AM_8{
public uint dwLength; j@V#IU9
public uint dwMemoryLoad; .*Tk&4
public uint dwTotalPhys; >Pa?I%.=
public uint dwAvailPhys; <634 PAO@
public uint dwTotalPageFile; lqu ]F /mv
public uint dwAvailPageFile; -yvP^E2O#?
public uint dwTotalVirtual; l&)O5<l'
public uint dwAvailVirtual; nQ56(~0
} A*r1!jz
//定义系统时间的信息结构 _'.
[StructLayout(LayoutKind.Sequential)] q{+!V
public struct SYSTEMTIME_INFO b^\6rT7t
{ . Rg_,Q\
public ushort wYear; $:5&qj,1
public ushort wMonth; .ObWG:
public ushort wDayOfWeek; v.vlkm
public ushort wDay; )*'|^W?+D
public ushort wHour; cS1vn8=C
public ushort wMinute; <i[73aMe
public ushort wSecond; d3#^;vw
public ushort wMilliseconds; Ms%=#-/Y
} k ;$JV~t
\YhySnD2
结构体定义的主体部分和C++中的没多大差别,具体每个结构体内部成员的定义可参考联机帮助中的SDK文档。同时,我们还发现在每个结构体定义的上面都有一句用中括号括起来的说明性文字。这些说明都是有关结构体成员的布局的,共有三种选项,分别说明如下: /ltja !
LayoutKind.Automatic:为了提高效率允许运行态对类型成员重新排序。 HRSo{noEq
注意:永远不要使用这个选项来调用不受管辖的动态链接库函数。 ]}GLpd
LayoutKind.Explicit:对每个域按照FieldOffset属性对类型成员排序 vJt+MM((rC
LayoutKind.Sequential:对出现在受管辖类型定义地方的不受管辖内存中的类型成员进行排序。 2/,tp1sj
在上面的程序中,为了方便起见我们都用到了第三种方式所有的API函数以及相关的结构体声明完毕后,我们就运用这些API来实现我们的程序功能――获取系统的相关信息。 )tGy[oz
界面可按如下方式布置,不过有兴趣的读者自然可以发挥自己的想象,将界面布局做得更好。 _Qh?<9-;_
简单的界面布置好后,我们添加一个按钮("获取信息"按钮)的消息处理函数如下: !!qbYLI
private void GetInfo_Click(object sender, System.EventArgs e) > 'v Ud%
{ ,J>RB BV
//调用GetWindowsDirectory和GetSystemDirectory函数分别取得Windows路径和系统路径 m$<02lU:W
const int nChars = 128; YV6t]jGyS
StringBuilder Buff = new StringBuilder(nChars); |+ *)y
GetWindowsDirectory(Buff,nChars); )#eM UF
WindowsDirectory.Text = "Windows路径:"+Buff.ToString(); / IAVt
GetSystemDirectory(Buff,nChars); zgcpW/2rc
SystemDirectory.Text = "系统路径:"+Buff.ToString(); [8)MLG"
//调用GetSystemInfo函数获取CPU的相关信息 ihq6jx
CPU_INFO CpuInfo; '?8a,yFcq
CpuInfo = new CPU_INFO(); 7qhGq@1qa
GetSystemInfo(ref CpuInfo); *MBd#lVIo
NumberOfProcessors.Text = "本计算机中有"+CpuInfo.dwNumberOfProcessors.ToString()+"个CPU"; " BkO.>x(
ProcessorType.Text = "CPU的类型为"+CpuInfo.dwProcessorType.ToString(); Cm7DD
ProcessorLevel.Text = "CPU等级为"+CpuInfo.dwProcessorLevel.ToString(); )8|SNTOd
OemId.Text = "CPU的OEM ID为"+CpuInfo.dwOemId.ToString(); ^f|m*">}9
PageSize.Text = "CPU中的页面大小为"+CpuInfo.dwPageSize.ToString(); gL0j!#d>
//调用GlobalMemoryStatus函数获取内存的相关信息 Y~C:G R$r
MEMORY_INFO MemInfo; 7|4u;Gd"
MemInfo = new MEMORY_INFO(); .B&,0A,
GlobalMemoryStatus(ref MemInfo); <oe xgjn;
MemoryLoad.Text = MemInfo.dwMemoryLoad.ToString()+"%的内存正在使用"; =ydn:[Sg
TotalPhys.Text = "物理内存共有"+MemInfo.dwTotalPhys.ToString()+"字节"; ;gB;V5co
AvailPhys.Text = "可使用的物理内存有"+MemInfo.dwAvailPhys.ToString()+"字节"; >B`3;s!2
TotalPageFile.Text = "交换文件总大小为"+MemInfo.dwTotalPageFile.ToString()+"字节"; H{pm5^KB
AvailPageFile.Text = "尚可交换文件大小为"+MemInfo.dwAvailPageFile.ToString()+"字节"; 9bQuni
TotalVirtual.Text = "总虚拟内存有"+MemInfo.dwTotalVirtual.ToString()+"字节"; \#7X%fGXL
AvailVirtual.Text = "未用虚拟内存有"+MemInfo.dwAvailVirtual.ToString()+"字节"; bNyWo5j
//调用GetSystemTime函数获取系统时间信息 S>=t< _d
SYSTEMTIME_INFO StInfo; &tS+
StInfo = new SYSTEMTIME_INFO(); @'-TrFJ
GetSystemTime(ref StInfo); K@*BR Hf#
Date.Text = StInfo.wYear.ToString()+"年"+StInfo.wMonth.ToString()+"月"+StInfo.wDay.ToString()+"日"; )8 ,Rev=
Time.Text = (StInfo.wHour+8).ToString()+"点"+StInfo.wMinute.ToString()+"分"+StInfo.wSecond.ToString()+"秒"; ULJhI???f
}