跳转至

Windows API 中的系统函数

原文: http://zetcode.com/gui/winapi/system/

在 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.libole32.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 教程的这一部分中,我们使用了一些系统函数。



回到顶部