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 教程中,我们使用了几个系统函数。