C# 调用 Win32 API 实现系统时间修改与磁盘序列号获取

小满
小满
发布时间:2026-10-14| 5人浏览过
原创

在 C# 开发中,有时需要直接与 Windows 底层系统进行交互,例如同步服务器时间与客户端时间,或者获取硬盘的唯一标识以用于软件授权验证。本文将展示如何通过 DllImport 调用 Kernel32.dll 中的关键函数,分别实现修改本地系统时间和获取磁盘卷序列号。

核心原理:P/Invoke 调用机制

C# 作为 .NET 语言,默认通过托管代码运行。要访问非托管的 Windows API(如修改系统时间的 SetLocalTime 和查询文件系统信息的 GetVolumeInformation),必须使用平台调用服务(Platform Invoke)。这需要在类中使用 [DllImport] 特性声明外部 DLL 路径,并定义对应的函数签名和数据结构。

准备工作:定义数据结构

在调用 API 之前,首先需要定义 Windows API 所需的数据结构。修改时间需要 SYSTEMTIME 结构,而获取卷信息需要特定的整型变量来接收返回值。

  1. 定义 SYSTEMTIME 结构:该结构包含年、月、日、时、分、秒等字段,对应 Windows API 的时间格式。必须确保字段类型与原生 C 结构体一致,使用 ushort 表示无符号短整型。
  2. 引入命名空间:需要引用 System.Runtime.InteropServices 以支持 DllImport 和 StructLayout 特性。
using System;
using System.Runtime.InteropServices;

namespace Fengyun
{
    public class Win32
    {
        // 定义 SYSTEMTIME 结构,布局紧凑以匹配原生结构体
        [StructLayout(LayoutKind.Sequential)]
        private 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;
        }
    }
}

第一步:修改本地系统时间

此步骤的目的是将程序指定的 DateTime 对象转换为 Windows 本地时间并应用。操作涉及声明 SetLocalTime 函数并封装调用逻辑。

第1步:声明 SetLocalTime API

  • 目的:告诉运行时去哪里找到修改时间的函数。
  • 动作:使用 DllImport("Kernel32.dll") 声明 SetLocalTime,参数为引用类型的 SYSTEMTIME 结构。
[DllImport("Kernel32.dll")] private static extern uint SetLocalTime(ref SYSTEMTIME lpSystemTime);

第2步:封装设置方法

  • 入口:输入一个 DateTime 类型的目标时间。
  • 动作:实例化 SYSTEMTIME 结构,将输入时间的各个部分赋值给结构体字段,然后调用 SetLocalTime。
  • 注意:修改系统时间通常需要管理员权限。
/// <summary>
/// 将本地时间与指定时间同步
/// </summary>
public static void SetTime(DateTime targetTime)
{
    SYSTEMTIME st = new SYSTEMTIME();
    st.wYear = Convert.ToUInt16(targetTime.Year);
    st.wMonth = Convert.ToUInt16(targetTime.Month);
    st.wDay = Convert.ToUInt16(targetTime.Day);
    st.wHour = Convert.ToUInt16(targetTime.Hour);
    st.wMinute = Convert.ToUInt16(targetTime.Minute);
    st.wSecond = Convert.ToUInt16(targetTime.Second);
    st.wMilliseconds = Convert.ToUInt16(targetTime.Millisecond);
    
    // 执行修改
    uint result = SetLocalTime(ref st);
    if (result == 0)
    {
        throw new Exception("设置系统时间失败,请检查权限。");
    }
}

第二步:获取硬盘序列号

获取硬盘序列号通常指的是获取文件系统的卷序列号(Volume Serial Number)。虽然这与物理硬盘的物理序列号不同,但在软件注册场景中常被用作设备指纹。我们使用 GetVolumeInformation API。

第1步:声明 GetVolumeInformation API

  • 目的:获取指定路径的文件系统信息。
  • 参数:包括根路径、卷名称缓冲区、最大组件长度、卷序列号引用、文件系统标志、文件系统名称缓冲区和缓冲区大小。
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern int GetVolumeInformation(
    string lpRootPathName,
    string lpVolumeNameBuffer,
    int nVolumeNameSize,
    ref int lpVolumeSerialNumber,
    int lpMaximumComponentLength,
    int lpFileSystemFlags,
    string lpFileSystemNameBuffer,
    int nFileSystemNameSize
);

第2步:封装获取方法

  • 入口:传入盘符字符串,如 "C"。
  • 动作:构造根路径 C:\,初始化缓冲区大小和输出变量,调用 API 并将返回的序列号转换为十六进制字符串。
/// <summary>
/// 获取指定盘符的卷序列号
/// </summary>
public static string GetDiskVolume(string drvID)
{
    const int MAX_FILENAME_LEN = 256;
    int serialNumber = 0;
    string volumeName = new string(' ', MAX_FILENAME_LEN);
    string fileSystemName = new string(' ', MAX_FILENAME_LEN);
    
    int result = GetVolumeInformation(
        drvID + @":\",
        volumeName,
        MAX_FILENAME_LEN,
        ref serialNumber,
        0,
        0,
        fileSystemName,
        MAX_FILENAME_LEN
    );
    
    if (result != 0)
    {
        // 返回十六进制格式,常用于唯一性识别
        return serialNumber.ToString("X8");
    }
    
    throw new Exception($"无法获取 {drvID} 盘的序列号。");
}

完成判断与安全提示

当 SetLocalTime 返回非零值,或 GetVolumeInformation 成功填充序列号变量时,表明操作成功。
风险提醒:修改系统时间会直接影响日志记录、证书验证及软件计时功能,建议在调试或非生产环境中谨慎使用,并在操作前后进行备份或通知用户。获取卷序列号仅依赖于文件系统,更换分区格式可能改变序列号,但不随硬件更换而改变(除非格式化)。

简要总结

本文通过 C# 示例代码展示了如何使用 Win32 API 进行系统级操作。通过定义 SYSTEMTIME 结构并调用 SetLocalTime,可实现时间同步;通过 GetVolumeInformation 可获取磁盘卷信息。这些技术点在实际软件开发中,特别是在需要绑定硬件特征或同步环境的场景中非常实用。以上就是 C# 利用 Win32 API 修改本地系统时间、获取硬盘序列号的详细内容,更多关于 C# 系统编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。