Windows API 中的系统函数
在 Windows API 教程的这一部分中,我们介绍了系统函数。 系统函数接收有关系统的信息并以各种方式与系统通信。
屏幕大小
GetSystemMetrics()
函数检索各种系统指标和系统配置设置。
screen_size.c
#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\Pelles C Projects\system\ScreenSize>ScreenSize.exe
The screen size is: 1280x800
屏幕大小为1280x800
。
锁定工作站
LockWorkStation()
锁定工作站的显示。
lock_workstation.c
#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 名称。 名称是在系统启动时建立的。
computer_name.c
#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\Pelles C Projects\system\ComputerName>ComputerName.exe
Computer name: ANDROMEDA
我们运行代码示例。
用户名
GetUserNameW()
函数返回用户名。
username.c
#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\Pelles C Projects\system\Username>username.exe
User name: Jano
这是username.exe
程序的示例输出。
当前目录
当前目录是用户所在或正在使用的目录。 在 Windows API 中,SetCurrentDirectoryW()
更改当前目录,GetCurrentDirectoryW()
检索当前目录。
current_directory.c
#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 版本
版本帮助器函数可用于确定当前的操作系统版本。
windows_version.c
#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\Pelles C Projects\system\WindowsVersion>WindowsVersion.exe
This is Windows 7
这是程序的示例输出。
内存
GlobalMemoryStatusEx()
检索有关系统当前对物理和虚拟内存使用情况的信息。
memory.c
#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\Pelles C Projects\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 标识的已知文件夹的完整路径。
documents_dir.c
#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;
}
该示例确定用户的Documents
目录的完整路径。 我们需要将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\Pelles C Projects\system\DocumentsDir>DocumentsDir.exe
C:\Users\Jano\Documents
这是DocumentsDir.exe
程序的示例输出。
驱动器名称
GetLogicalDriveStringsW()
函数使用指定系统中有效驱动器的字符串填充缓冲区。
get_drives.c
#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()
被调用。 缓冲区中填充了以零结尾的字符串,这些字符串代表设备名称。 该函数的第一个参数是指定缓冲区的最大大小。 缓冲区是第二个参数。
wchar_t *SingleDrive = LogicalDrives;
while(*SingleDrive) {
wprintf(L"%ls\n", SingleDrive);
SingleDrive += wcslen(SingleDrive) + 1;
}
我们遍历设备名称数组并将其打印到控制台。
C:\Users\Jano\Documents\Pelles C Projects\system\GetDrives>GetDrives.exe
C:\
D:\
系统上有两个驱动器:C:\
和D:\
。
可用空间
GetDiskFreeSpaceExW()
检索有关磁盘卷上可用空间量的信息。 该函数提供三段信息:总空间量,可用空间量以及与调用线程关联的用户可用的可用空间。
free_disk_space.c
#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\Pelles C Projects\system\FreeDiskSpace>FreeDiskSpace.exe
Available space to caller: 20377 MB
Total space: 69999 MB
Free space on drive: 20377 MB
这是FreeDiskSpace.exe
程序的示例输出。
CPU 速度
可以通过检查注册表值来确定 CPU 速度。 该值将在安装过程中写入注册表。 我们需要查询HARDWARE\DESCRIPTION\System\CentralProcessor\0
键。
cpu_speed.c
#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\Pelles C Projects\system\CpuSpeed>CpuSpeed.exe
CPU speed: 2394 MHz
这是CpuSpeed.exe
程序的示例输出。
在 Windows API 教程的这一部分中,我们使用了一些系统函数。