Windows API 中的系统函数
最后修改于 2023 年 10 月 18 日
在本 Windows API 教程中,我们将介绍系统函数。系统函数接收有关系统的信息,并以各种方式与系统通信。
屏幕尺寸
GetSystemMetrics
函数检索各种系统指标和系统配置设置。
#include <windows.h> #include <wchar.h> #pragma comment(lib, "user32.lib") int wmain(void) { int x = GetSystemMetrics(SM_CXSCREEN); int y = GetSystemMetrics(SM_CYSCREEN); wprintf(L"The screen size is: %dx%d\n", x, y); return 0; }
该代码示例将屏幕尺寸打印到控制台。
#pragma comment(lib, "user32.lib")
程序需要 user32.lib
库才能编译。
int x = GetSystemMetrics(SM_CXSCREEN); int y = GetSystemMetrics(SM_CYSCREEN);
我们使用 GetSystemMetrics
确定屏幕分辨率。
C:\Users\Jano\Documents\WinApi\system\ScreenSize>ScreenSize.exe The screen size is: 1280x800
屏幕尺寸为 1280x800。
锁定工作站
LockWorkStation
锁定工作站的显示器。
#include <windows.h> #include <wchar.h> #pragma comment(lib, "user32.lib") int wmain(void) { int r = LockWorkStation(); if (r == 0) { wprintf(L"LockWorkStation() failed %d\n", GetLastError()); return 1; } return 0; }
程序需要 user32.lib
才能编译。
计算机名称
GetComputerNameEx
函数检索与本地计算机关联的 NetBIOS 或 DNS 名称。 这些名称是在系统启动时建立的。
#include <windows.h> #include <wchar.h> int wmain(void) { wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = sizeof(computerName) / sizeof(computerName[0]); int r = GetComputerNameW(computerName, &size); if (r == 0) { wprintf(L"Failed to get computer name %ld", GetLastError()); return 1; } wprintf(L"Computer name: %ls\n", computerName); return 0; }
该示例将计算机名称打印到控制台。
wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1];
MAX_COMPUTERNAME_LENGTH
常量确定计算机名称的最大长度。
int r = GetComputerNameW(computerName, &size);
我们使用 GetComputerNameW
函数获取计算机的名称。 该名称存储在 computerName
数组中。
C:\Users\Jano\Documents\WinApi\system\ComputerName>ComputerName.exe Computer name: ANDROMEDA
用户名
GetUserNameW
函数返回用户名。
#include <windows.h> #include <Lmcons.h> #include <wchar.h> int wmain(void) { wchar_t username[UNLEN+1]; DWORD len = sizeof(username) / sizeof(wchar_t); int r = GetUserNameW(username, &len); if (r == 0) { wprintf(L"Failed to get username %ld", GetLastError()); return 1; } wprintf(L"User name: %ls\n", username); return 0; }
该示例将用户名打印到控制台。
#include <Lmcons.h>
Lmcons.h
文件定义了 ULEN
常量。
wchar_t username[UNLEN+1];
ULEN
常量定义用户名的最大长度。
int r = GetUserNameW(username, &len);
GetUserNameW
函数检索用户名并将其存储在 username
数组中。
C:\Users\Jano\Documents\WinApi\system\Username>username.exe User name: Jano
当前目录
当前目录 是用户所在或正在使用的目录。在 Windows API 中,SetCurrentDirectoryW
更改当前目录,而 GetCurrentDirectoryW
检索当前目录。
#include <windows.h> #include <wchar.h> #define BUFSIZE MAX_PATH int wmain(int argc, wchar_t **argv) { wchar_t buf[BUFSIZE]; if (argc != 2) { wprintf(L"Usage: %ls <dir>\n", argv[0]); return 1; } DWORD r = SetCurrentDirectoryW(argv[1]); if (r == 0) { wprintf(L"SetCurrentDirectoryW() failed (%ld)\n", GetLastError()); return 1; } r = GetCurrentDirectoryW(BUFSIZE, buf); if (r == 0) { wprintf(L"GetCurrentDirectoryW() failed (%ld)\n", GetLastError()); return 1; } if (r > BUFSIZE) { wprintf(L"Buffer too small; needs %d characters\n", r); return 1; } wprintf(L"Current directory is: %ls\n", buf); return 0; }
在代码示例中,我们更改并打印当前工作目录。该程序接收一个命令行参数——要更改到的目录。
#define BUFSIZE MAX_PATH
我们使用 MAX_PATH
常量,该常量定义系统路径的最大长度。
if (argc != 2) { wprintf(L"Usage: %ls <dir>\n", argv[0]); return 1; }
如果我们没有向程序传递参数,则会打印一条错误消息。
DWORD r = SetCurrentDirectoryW(argv[1]);
我们使用 SetCurrentDirectoryW
更改为作为参数传递的目录。
r = GetCurrentDirectoryW(BUFSIZE, buf);
我们使用 GetCurrentDirectoryW
函数调用获取当前工作目录。
if (r > BUFSIZE) { wprintf(L"Buffer too small; needs %d characters\n", r); return 1; }
如果返回值大于 BUFSIZE
,则缓冲区太小。
Windows 版本
可以使用版本帮助程序函数来确定当前的操作系统版本。
#include <windows.h> #include <wchar.h> #include <VersionHelpers.h> int wmain(void) { //if (IsWindows10OrGreater()) { // wprintf(L"This is Windows 10+"); // } if (IsWindows8Point1OrGreater()) { wprintf(L"This is Windows 8.1+\n"); } else if (IsWindows8OrGreater()) { wprintf(L"This is Windows 8\n"); } else if (IsWindows7OrGreater ()) { wprintf(L"This is Windows 7\n"); } else if (IsWindowsVistaOrGreater ()) { wprintf(L"This is Windows Vista\n"); } else if (IsWindowsXPOrGreater()) { wprintf(L"This is Windows XP\n"); } return 0; }
我们使用版本帮助程序函数来确定操作系统版本。
#include <VersionHelpers.h>
帮助程序函数在 VersionHelpers.h
文件中声明。
//if (IsWindows10OrGreater()) { // wprintf(L"This is Windows 10+"); // }
在撰写本文时,Pelles C 的 SDK 中未定义 IsWindows10OrGreater
。
if (IsWindows8Point1OrGreater()) { wprintf(L"This is Windows 8.1+\n"); }
如果当前版本是 Windows 8.1 或更高版本,则 IsWindows8Point1OrGreater
返回 true。
C:\Users\Jano\Documents\WinApi\system\WindowsVersion>WindowsVersion.exe This is Windows 7
Memory
GlobalMemoryStatusEx
检索有关系统当前对物理内存和虚拟内存的使用情况的信息。
#include <windows.h> #include <wchar.h> int wmain(void) { MEMORYSTATUSEX mem = {0}; mem.dwLength = sizeof(mem); int r = GlobalMemoryStatusEx(&mem); if (r == 0) { wprintf(L"Failed to memory status %ld", GetLastError()); return 1; } wprintf(L"Memory in use: %ld percent\n", mem.dwMemoryLoad); wprintf(L"Total physical memory: %lld\n", mem.ullTotalPhys); wprintf(L"Free physical memory: %lld\n", mem.ullAvailPhys); wprintf(L"Total virtual memory: %lld\n", mem.ullTotalVirtual); wprintf(L"Free virtual memory: %lld\n", mem.ullAvailVirtual); return 0; }
该程序将有关内存使用情况的统计信息打印到控制台。
MEMORYSTATUSEX mem = {0};
GlobalMemoryStatusEx
函数将有关内存状态的信息存储在 MEMORYSTATUSEX
结构中。
int r = GlobalMemoryStatusEx(&mem);
执行 GlobalMemoryStatusEx
函数;信息存储在该结构中。
wprintf(L"Memory in use: %ld percent\n", mem.dwMemoryLoad);
dwMemoryLoad
成员指定物理内存的近似百分比。
wprintf(L"Total physical memory: %lld\n", mem.ullTotalPhys);
ullTotalPhys
成员指定以字节为单位的实际物理内存。
wprintf(L"Free physical memory: %lld\n", mem.ullAvailPhys);
ullTotalPhys
成员指定当前可用的物理内存量(以字节为单位)。
wprintf(L"Total virtual memory: %lld\n", mem.ullTotalVirtual);
ullTotalVirtual
成员指定虚拟内存的总量(以字节为单位)。
wprintf(L"Free virtual memory: %lld\n", mem.ullAvailVirtual);
ullAvailVirtual
成员指定可用虚拟内存的量(以字节为单位)。
C:\Users\Jano\Documents\WinApi\system\Memory>Memory.exe Memory in use: 47 percent Total physical memory: 4226072576 Free physical memory: 2229788672 Total virtual memory: 8796092891136 Free virtual memory: 8796052586496
已知文件夹
自 Windows Vista 以来,用于识别 Windows 中重要目录的新系统。它被称为 已知文件夹。已知文件夹使用一组 GUID(全局唯一标识符)值来引用重要文件夹。
SHGetKnownFolderPath
函数检索由文件夹 ID 标识的已知文件夹的完整路径。
#include <windows.h> #include <initguid.h> #include <KnownFolders.h> #include <ShlObj.h> #include <wchar.h> int wmain(void) { PWSTR path = NULL; HRESULT hr = SHGetKnownFolderPath(&FOLDERID_Documents, 0, NULL, &path); if (SUCCEEDED(hr)) { wprintf(L"%ls\n", path); } CoTaskMemFree(path); return 0; }
该示例确定用户“文档”目录的完整路径。我们需要将 shell32.lib
和 ole32.lib
添加到项目库中。
#include <initguid.h>
由于某些内部 API 问题,我们需要包含 initguid.h
文件;否则,该示例不会编译。它会因 Unresolved external symbol 'FOLDERID_Documents'
错误而失败。
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_Documents, 0, NULL, &path);
SHGetKnownFolderPath
用于确定“文档”目录的路径。
if (SUCCEEDED(hr)) { wprintf(L"%ls\n", path); }
SUCCEEDED
宏可用于确定函数调用是否成功。
CoTaskMemFree(path);
最后,有必要使用 CoTaskMemFree
函数释放已分配的内存。
C:\Users\Jano\Documents\WinApi\system\DocumentsDir>DocumentsDir.exe C:\Users\Jano\Documents
驱动器名称
GetLogicalDriveStringsW
函数使用指定系统中有效驱动器的字符串填充缓冲区。
#include <windows.h> #include <wchar.h> int wmain(void) { wchar_t LogicalDrives[MAX_PATH] = {0}; DWORD r = GetLogicalDriveStringsW(MAX_PATH, LogicalDrives); if (r == 0) { wprintf(L"Failed to get drive names %ld", GetLastError()); return 1; } if (r > 0 && r <= MAX_PATH) { wchar_t *SingleDrive = LogicalDrives; while (*SingleDrive) { wprintf(L"%ls\n", SingleDrive); SingleDrive += wcslen(SingleDrive) + 1; } } return 0; }
该示例打印系统中有效的驱动器。
wchar_t LogicalDrives[MAX_PATH] = {0};
驱动器名称是一种路径类型,因此 MAX_PATH
常量与其最大长度相关。LogicalDrives
是一个字符串数组,用作 GetLogicalDriveStringsW
函数的缓冲区。
DWORD r = GetLogicalDriveStringsW(MAX_PATH, LogicalDrives);
调用 GetLogicalDriveStringsW
。 缓冲区填充以 null 结尾的字符串,这些字符串表示设备名称。 函数的第一个参数是指定缓冲区的最大大小。 缓冲区是第二个参数。
wchar_t *SingleDrive = LogicalDrives; while (*SingleDrive) { wprintf(L"%ls\n", SingleDrive); SingleDrive += wcslen(SingleDrive) + 1; }
我们遍历设备名称的数组,并将它们打印到控制台。
C:\Users\Jano\Documents\WinApi\system\GetDrives>GetDrives.exe C:\ D:\
系统上有两个驱动器:C:\
和 D:\
。
可用空间
GetDiskFreeSpaceExW
检索有关磁盘卷上可用空间量的信息。 该函数提供了三条信息:总空间量、可用空间量和与调用线程关联的用户的可用空间。
#include <windows.h> #include <wchar.h> int wmain(void) { unsigned __int64 freeCall, total, free; int r = GetDiskFreeSpaceExW(L"C:\\", (PULARGE_INTEGER) &freeCall, (PULARGE_INTEGER) &total, (PULARGE_INTEGER) &free); if (r == 0) { wprintf(L"Failed to get free disk space %ld", GetLastError()); return 1; } wprintf(L"Available space to caller: %I64u MB\n", freeCall / (1024*1024)); wprintf(L"Total space: %I64u MB\n", total / (1024*1024)); wprintf(L"Free space on drive: %I64u MB\n", free / (1024*1024)); return 0; }
该示例检查 C:\
驱动器上的磁盘空间。
unsigned __int64 freeCall, total, free;
数量以字节为单位表示;这些数字可能非常大。 使用 unsigned __int64
类型,它是一个能够存储非常大值的正 64 位整数。
int r = GetDiskFreeSpaceExW(L"C:\\", (PULARGE_INTEGER) &freeCall, (PULARGE_INTEGER) &total, (PULARGE_INTEGER) &free);
调用 GetDiskFreeSpaceExW
。
wprintf(L"Available space to caller: %I64u MB\n", freeCall / (1024*1024)); wprintf(L"Total space: %I64u MB\n", total / (1024*1024)); wprintf(L"Free space on drive: %I64u MB\n", free / (1024*1024));
这三个数量使用 wprintf
函数打印到控制台。 这些值以 MB 为单位表示。
C:\Users\Jano\Documents\WinApi\system\FreeDiskSpace>FreeDiskSpace.exe Available space to caller: 20377 MB Total space: 69999 MB Free space on drive: 20377 MB
CPU 速度
可以通过检查注册表值来确定 CPU 速度。 该值在安装期间写入注册表。 我们需要查询 HARDWARE\DESCRIPTION\System\CentralProcessor\0
键。
#include <windows.h> #include <wchar.h> int wmain(void) { DWORD BufSize = MAX_PATH; DWORD mhz = MAX_PATH; HKEY key; long r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &key); if (r != ERROR_SUCCESS) { wprintf(L"RegOpenKeyExW() failed %ld", GetLastError()); return 1; } r = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE) &mhz, &BufSize); if (r != ERROR_SUCCESS) { wprintf(L"RegQueryValueExW() failed %ld", GetLastError()); return 1; } wprintf(L"CPU speed: %lu MHz\n", mhz); r = RegCloseKey(key); if (r != ERROR_SUCCESS) { wprintf(L"Failed to close registry handle %ld", GetLastError()); return 1; } return 0; }
该示例确定 CPU 速度。
long r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &key);
RegOpenKeyExW
函数用于打开提供的注册表项。
r = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE) &mhz, &BufSize);
该值使用 RegQueryValueExW
函数读取。
r = RegCloseKey(key);
RegCloseKey
关闭注册表句柄。
C:\Users\Jano\Documents\WinApi\system\CpuSpeed>CpuSpeed.exe CPU speed: 2394 MHz
在本 Windows API 教程中,我们使用了几个系统函数。