C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#调用Windows API

通过C#调用Windows API的具体方法

作者:墨夶

在开发系统监控工具、性能分析器或自动化管理程序时,Windows API 是你与操作系统对话的桥梁,通过C#调用Windows API可以直接访问系统底层数据、实现注册表读写与电源状态监控以及无需额外依赖,纯原生代码实现,所以本文给大家介绍了具体的调用方法,需要的朋友可以参考下

为什么你需要掌握Windows API调用?

在开发系统监控工具、性能分析器或自动化管理程序时,Windows API 是你与操作系统对话的桥梁。

通过C#调用Windows API

一、基础篇:调用API的核心技巧

1.1 DllImport声明与结构体定义

using System;
using System.Runtime.InteropServices;

// 定义Windows API函数签名
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern uint GetSystemInfo(out SYSTEM_INFO lpSystemInfo);

// 对应的结构体定义(按字段顺序与API匹配)
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
    public ushort processorArchitecture; // 处理器架构
    public ushort reserved;             // 保留字段
    public uint pageSize;               // 页面大小
    public IntPtr minimumApplicationAddress; // 应用程序最低地址
    public IntPtr maximumApplicationAddress; // 应用程序最高地址
    public IntPtr activeProcessorMask;  // 活跃处理器掩码
    public uint numberOfProcessors;     // 处理器数量
    public uint processorType;          // 处理器类型
    public uint allocationGranularity;  // 内存分配粒度
    public ushort processorLevel;       // 处理器级别
    public ushort processorRevision;    // 处理器修订号
}

关键细节

1.2 调用示例:获取系统基本信息

public static void GetSystemHardwareInfo()
{
    SYSTEM_INFO sysInfo;
    if (GetSystemInfo(out sysInfo) != 0)
    {
        Console.WriteLine($"处理器架构: {sysInfo.processorArchitecture}");
        Console.WriteLine($"处理器数量: {sysInfo.numberOfProcessors}");
        Console.WriteLine($"页面大小: {sysInfo.pageSize} bytes");
        Console.WriteLine($"内存分配粒度: {sysInfo.allocationGranularity} bytes");
    }
    else
    {
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }
}

输出示例

处理器架构: 9(x64)
处理器数量: 8
页面大小: 4096 bytes
内存分配粒度: 65536 bytes

二、进阶篇:深度系统信息获取

2.1 获取CPU详细信息(注册表方式)

// 注册表API声明
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern long RegOpenKeyEx(
    IntPtr hKey, 
    string subKey, 
    uint ulOptions, 
    RegSAM samDesired, 
    out IntPtr phkResult);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern long RegQueryValueEx(
    IntPtr hKey, 
    string lpValueName, 
    uint lpReserved, 
    out uint lpType, 
    byte[] lpData, 
    ref uint lpcbData);

// 注册表根键常量
private const int HKEY_LOCAL_MACHINE = -2147483642;

// 访问权限标志
[Flags]
public enum RegSAM : uint
{
    QueryValue = 0x0001,
    EnumerateSubKeys = 0x0008
}

// 获取CPU名称
public static string GetCpuName()
{
    IntPtr hKey;
    const string keyPath = @"HARDWARE\DESCRIPTION\System\CentralProcessor\0";
    
    // 打开注册表键
    long result = RegOpenKeyEx(
        (IntPtr)HKEY_LOCAL_MACHINE, 
        keyPath, 
        0, 
        RegSAM.QueryValue, 
        out hKey);
    
    if (result != 0)
    {
        throw new Win32Exception((int)result);
    }

    // 查询ProcessorNameString值
    uint dataType = 0;
    uint dataSize = 1024;
    byte[] dataBuffer = new byte[dataSize];
    
    result = RegQueryValueEx(
        hKey, 
        "ProcessorNameString", 
        0, 
        out dataType, 
        dataBuffer, 
        ref dataSize);
    
    if (result != 0)
    {
        throw new Win32Exception((int)result);
    }

    // 转换为字符串并清理无效字符
    return Encoding.Default.GetString(dataBuffer).Trim('\0');
}

实际应用

Console.WriteLine($"CPU型号: {GetCpuName()}");
// 输出示例: "Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz"

2.2 获取系统时间与电源状态

// 获取系统时间
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void GetSystemTime(ref SYSTEMTIME st);

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
    public ushort wYear;
    public ushort wMonth;
    public ushort wDayOfWeek;
    public ushort wDay;
    public ushort wHour;
    public ushort wMinute;
    public ushort wSecond;
    public ushort wMilliseconds;
}

// 获取电源状态
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetSystemPowerStatus(ref SYSTEM_POWER_STATUS powerStatus);

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_POWER_STATUS
{
    public byte ACLineStatus;         // 交流电源状态
    public byte BatteryFlag;          // 电池标志
    public byte BatteryLifePercent;   // 电池百分比
    public byte Reserved1;
    public uint BatteryLifeTime;      // 剩余时间(秒)
    public uint BatteryFullLifeTime;  // 总容量(秒)
}

调用示例

public static void GetSystemTimeAndPowerStatus()
{
    SYSTEMTIME sysTime = new SYSTEMTIME();
    GetSystemTime(ref sysTime);
    
    Console.WriteLine($"系统时间: {sysTime.wYear}-{sysTime.wMonth}-{sysTime.wDay} {sysTime.wHour}:{sysTime.wMinute}:{sysTime.wSecond}");

    SYSTEM_POWER_STATUS powerStatus = new SYSTEM_POWER_STATUS();
    if (GetSystemPowerStatus(ref powerStatus))
    {
        string acStatus = powerStatus.ACLineStatus == 1 ? "已连接" : "未连接";
        string batteryStatus = powerStatus.BatteryFlag switch
        {
            1 => "电量不足",
            2 => "正在充电",
            4 => "电池未安装",
            _ => "未知状态"
        };

        Console.WriteLine($"电源状态: {acStatus}");
        Console.WriteLine($"电池状态: {batteryStatus}");
        Console.WriteLine($"剩余电量: {powerStatus.BatteryLifePercent}%");
        Console.WriteLine($"剩余时间: {powerStatus.BatteryLifeTime / 3600}小时{(powerStatus.BatteryLifeTime % 3600) / 60}分钟");
    }
}

输出示例

系统时间: 2025-07-19 18:06:48
电源状态: 已连接
电池状态: 正在充电
剩余电量: 85%
剩余时间: 3小时45分钟

三、实战篇:综合系统信息收集器

3.1 项目结构设计

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("=== 系统信息收集器 ===\n");
        
        // 获取硬件信息
        GetSystemHardwareInfo();
        Console.WriteLine("\n=== CPU信息 ===");
        Console.WriteLine($"CPU型号: {GetCpuName()}");
        
        // 获取时间与电源状态
        Console.WriteLine("\n=== 系统时间与电源 ===");
        GetSystemTimeAndPowerStatus();
        
        // 获取内存信息
        Console.WriteLine("\n=== 内存信息 ===");
        GetMemoryInfo();
        
        Console.WriteLine("\n=== 网络信息 ===");
        GetNetworkInfo();
    }
}

3.2 获取内存信息

// 获取内存信息
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GlobalMemoryStatus(ref MEMORYSTATUS lpBuffer);

[StructLayout(LayoutKind.Sequential)]
public struct MEMORYSTATUS
{
    public uint dwLength;
    public uint dwMemoryLoad;         // 内存使用百分比
    public ulong ullTotalPhys;        // 物理内存总量
    public ulong ullAvailPhys;        // 可用物理内存
    public ulong ullTotalPageFile;    // 页面文件总量
    public ulong ullAvailPageFile;    // 可用页面文件
    public ulong ullTotalVirtual;     // 虚拟内存总量
    public ulong ullAvailVirtual;     // 可用虚拟内存
}

public static void GetMemoryInfo()
{
    MEMORYSTATUS memoryStatus = new MEMORYSTATUS();
    memoryStatus.dwLength = (uint)Marshal.SizeOf(memoryStatus);
    
    if (!GlobalMemoryStatus(ref memoryStatus))
    {
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    Console.WriteLine($"内存使用率: {memoryStatus.dwMemoryLoad}%");
    Console.WriteLine($"物理内存总量: {memoryStatus.ullTotalPhys / 1024 / 1024} MB");
    Console.WriteLine($"可用物理内存: {memoryStatus.ullAvailPhys / 1024 / 1024} MB");
    Console.WriteLine($"虚拟内存总量: {memoryStatus.ullTotalVirtual / 1024 / 1024} MB");
    Console.WriteLine($"可用虚拟内存: {memoryStatus.ullAvailVirtual / 1024 / 1024} MB");
}

3.3 获取网络信息

// 获取网络适配器信息
[DllImport("iphlpapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint GetAdaptersInfo(IntPtr pAdapterInfo, ref uint pOutBufLen);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct IP_ADAPTER_INFO
{
    public uint ComboIndex;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string AdapterName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string Description;
    public uint AddressLength;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] Address;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string AddressString;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DnsName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DnsSuffix;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DnsDescription;
    public uint PhysicalAddressLength;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] PhysicalAddress;
    public uint Flags;
    public uint Mtu;
    public uint IfType;
    public uint EnableType;
    public uint OperStatus;
    public uint Ipv6IfIndex;
    public uint ZoneIndices;
    public IntPtr FirstUnicastAddress;
    public IntPtr FirstAnycastAddress;
    public IntPtr FirstMulticastAddress;
    public IntPtr FirstDnsServerAddress;
    public IntPtr FirstDnsSuffix;
}

public static void GetNetworkInfo()
{
    uint bufferSize = 15000;
    IntPtr buffer = Marshal.AllocHGlobal((int)bufferSize);
    
    uint result = GetAdaptersInfo(buffer, ref bufferSize);
    
    if (result == 0)
    {
        IP_ADAPTER_INFO adapterInfo = (IP_ADAPTER_INFO)Marshal.PtrToStructure(buffer, typeof(IP_ADAPTER_INFO));
        
        Console.WriteLine($"适配器名称: {adapterInfo.AdapterName}");
        Console.WriteLine($"描述: {adapterInfo.Description}");
        Console.WriteLine($"MAC地址: {BitConverter.ToString(adapterInfo.Address).Replace("-", ":")}");
        Console.WriteLine($"IP地址: {adapterInfo.AddressString}");
    }
    else
    {
        throw new Win32Exception((int)result);
    }
    
    Marshal.FreeHGlobal(buffer);
}

四、性能优化与注意事项

4.1 内存安全与异常处理

4.2 跨平台兼容性

#if WINDOWS
// Windows-specific code
#else
// Cross-platform code
#endif

五、 何时选择哪种方法?

需求推荐方法典型示例
获取CPU型号注册表读取(RegQueryValueEx)GetCpuName()
获取系统时间GetSystemTimeGetSystemTimeAndPowerStatus()
获取内存信息GlobalMemoryStatusGetMemoryInfo()
获取网络适配器信息GetAdaptersInfoGetNetworkInfo()
获取电源状态GetSystemPowerStatusGetSystemTimeAndPowerStatus()

立即行动

  1. 升级代码:将.NET Environment替换为原生API获取更详细信息
  2. 重构工具:将现有系统监控工具改为API调用以提升性能
  3. 探索注册表:尝试读取其他系统配置信息(如启动项、服务列表)

以上就是C#调用Windows API的具体方法的详细内容,更多关于C#调用Windows API的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文