開發一個集定時關機、倒計時關機、關機提醒、系統信息查看於一體的 Windows 工具,深度演示 C# 調用 Windows API(user32.dll、kernel32.dll、shell32.dll)的完整流程。
using System.Runtime.InteropServices;
using System.Text;
public partial class MainForm : Form
{
// user32.dll - 窗口與關機
[DllImport("user32.dll")]
public static extern long ExitWindowsEx(long uFlags, long dwReserved);
[DllImport("user32.dll")]
public static extern long SetWindowPos(long hwnd, long hWndInsertAfter,
long x, long y, long cx, long cy, long wFlags);
// shell32.dll - 系統關於信息
[DllImport("shell32.dll")]
public static extern long ShellAbout(long hWnd, string szApp, string szOtherStuff, long hIcon);
// kernel32.dll - 系統信息獲取
[DllImport("kernel32.dll")]
public static extern void GetWindowsDirectory(StringBuilder lpBuffer, int nSize);
[DllImport("kernel32.dll")]
public static extern void GetSystemDirectory(StringBuilder lpBuffer, int nSize);
[DllImport("kernel32.dll")]
public static extern void GetSystemInfo(ref CPU_INFO lpSystemInfo);
[DllImport("kernel32.dll")]
public static extern void GlobalMemoryStatus(ref MEMORY_INFO lpBuffer);
[DllImport("kernel32.dll")]
public static extern void GetSystemTime(ref SYSTEMTIME_INFO lpSystemTime);
}
[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;
}
private const int SHUTDOWN = 1;
private const int REBOOT = 2;
private const int LOGOFF = 0;
private long dwReserved = 0;
private void ExecuteShutdown(int action)
{
long result = action switch
{
SHUTDOWN => ExitWindowsEx(SHUTDOWN | 0x04, dwReserved), // EWX_FORCE
REBOOT => ExitWindowsEx(REBOOT | 0x04, dwReserved),
LOGOFF => ExitWindowsEx(LOGOFF | 0x04, dwReserved),
_ => 0
};
if (result == 0)
{
int error = Marshal.GetLastWin32Error();
MessageBox.Show($"操作失敗,錯誤碼: {error}");
}
}
// 按鈕事件綁定
private void btnShutdown_Click(object sender, EventArgs e) => ExecuteShutdown(SHUTDOWN);
private void btnReboot_Click(object sender, EventArgs e) => ExecuteShutdown(REBOOT);
private void btnLogoff_Click(object sender, EventArgs e) => ExecuteShutdown(LOGOFF);
private int _countdownSeconds = 0;
private void timer1_Tick(object sender, EventArgs e)
{
// 1. 更新當前時間顯示
lblCurrentTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// 2. 定時關機檢查
if (chkSchedule.Checked)
{
DateTime target = dtpDate.Value.Date + dtpTime.Value.TimeOfDay;
if (DateTime.Now >= target)
{
ExecuteShutdown(SHUTDOWN);
timer1.Stop();
}
}
// 3. 倒計時關機
if (chkCountdown.Checked)
{
if (_countdownSeconds > 0)
{
_countdownSeconds--;
lblCountdown.Text = $"剩餘: {_countdownSeconds} 秒";
}
else
{
ExecuteShutdown(SHUTDOWN);
timer1.Stop();
}
}
// 4. 定時報警
if (chkAlarm.Checked && DateTime.Now >= dtpAlarm.Value)
{
MessageBox.Show("定時提醒到達!");
chkAlarm.Checked = false; // 單次觸發
}
}
// 啟動倒計時
private void btnStartCountdown_Click(object sender, EventArgs e)
{
_countdownSeconds = (int)numCountdown.Value; // NumericUpDown 設置秒數
chkCountdown.Checked = true;
}
public partial class SysInfoForm : Form
{
private void btnRefresh_Click(object sender, EventArgs e)
{
// 1. 系統路徑
StringBuilder sb = new StringBuilder(256);
GetWindowsDirectory(sb, sb.Capacity);
txtWinDir.Text = sb.ToString();
GetSystemDirectory(sb, sb.Capacity);
txtSysDir.Text = sb.ToString();
// 2. CPU 信息
CPU_INFO cpu = new CPU_INFO();
GetSystemInfo(ref cpu);
txtCpuCount.Text = cpu.dwNumberOfProcessors.ToString();
txtCpuType.Text = cpu.dwProcessorType.ToString();
txtCpuLevel.Text = cpu.dwProcessorLevel.ToString();
// 3. 內存信息
MEMORY_INFO mem = new MEMORY_INFO { dwLength = (uint)Marshal.SizeOf() };
GlobalMemoryStatus(ref mem);
txtMemLoad.Text = $"{mem.dwMemoryLoad}%";
txtTotalPhys.Text = FormatBytes(mem.dwTotalPhys);
txtAvailPhys.Text = FormatBytes(mem.dwAvailPhys);
// 4. 系統時間 (UTC)
SYSTEMTIME_INFO st = new SYSTEMTIME_INFO();
GetSystemTime(ref st);
txtSysTime.Text = $"{st.wYear}-{st.wMonth:D2}-{st.wDay:D2} {st.wHour:D2}:{st.wMinute:D2}:{st.wSecond:D2} (UTC)";
}
private string FormatBytes(uint bytes)
{
double gb = bytes / 1024.0 / 1024 / 1024;
return gb >= 1 ? $"{gb:F2} GB" : $"{bytes / 1024 / 1024} MB";
}
}
[StructLayout(LayoutKind.Sequential)] 確保字段順序與 C++ 結構一致StringBuilder 配合容量參數防止緩衝區溢出ref 關鍵字Marshal.GetLastWin32Error() 獲取錯誤碼requireAdministratorSystem.Management (WMI) 替代 kernel32 API 獲取硬件信息(托管代碼、跨平台)PerformanceCounter 類獲取實時 CPU/內存使用率Process.Start("shutdown.exe", "/s /t 0") 避免 P/Invoke 複雜度本項目完整演示了 C# P/Invoke 技術棧的核心用法:API 聲明、結構體映射、字符串緩衝、錯誤處理、定時器調度,是學習 Windows 系統編程的優秀實戰案例。