windows API函数之文件类函数(二)

3.26 函数名:GetFileTime

(1)函数的概述

GetFileTime 是一个Windows API函数,它用于检索指定文件或目录的创建、访问和最后写入时间。这些时间以FILETIME结构的形式返回,该结构表示自1601年1月1日(UTC)起的100纳秒间隔数。

(2)函数所在的动态链接库

GetFileTime 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL GetFileTime(  
  HANDLE     hFile,  
  LPFILETIME lpCreationTime,  
  LPFILETIME lpLastAccessTime,  
  LPFILETIME lpLastWriteTime  
);

(4)各参数及返回值的详细解释

  • hFile(输入参数):类型:HANDLE,描述:一个已打开的文件或目录的句柄。
  • lpCreationTime(输出参数):类型:LPFILETIME(指向FILETIME结构的指针),描述:指向接收文件创建时间的FILETIME结构的指针。
  • lpLastAccessTime(输出参数):类型:LPFILETIME(指向FILETIME结构的指针),描述:指向接收文件最后访问时间的FILETIME结构的指针。
  • lpLastWriteTime(输出参数):类型:LPFILETIME(指向FILETIME结构的指针),描述:指向接收文件最后写入时间的FILETIME结构的指针。
  • 返回值:类型:BOOL,描述:如果函数成功,返回值为非零。如果函数失败,返回值为零。要获取扩展的错误信息,可以调用GetLastError。

(5)函数的详细作用

GetFileTime函数用于检索与指定文件或目录句柄相关联的创建、访问和最后写入时间。这些时间戳对于文件管理和监视文件更改非常有用。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
#include <ctime>  
#include <iomanip>  
  
void ConvertFileTimeToLocalTime(const FILETIME& ft, SYSTEMTIME& st) {  
    FILETIME localFileTime;  
    FileTimeToLocalFileTime(&ft, &localFileTime);  
    FileTimeToSystemTime(&localFileTime, &st);  
}  
  
void PrintFileTime(const FILETIME& ft) {  
    SYSTEMTIME st;  
    ConvertFileTimeToLocalTime(ft, st);  
  
    std::cout << std::put_time(&st, "%Y-%m-%d %H:%M:%S") << std::endl;  
}  
  
int main() {  
    HANDLE hFile = CreateFileA(  
        "C:\\example\\test.txt",  
        GENERIC_READ,  
        FILE_SHARE_READ,  
        NULL,  
        OPEN_EXISTING,  
        FILE_ATTRIBUTE_NORMAL,  
        NULL  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed." << std::endl;  
        return 1;  
    }  
  
    FILETIME ftCreate, ftAccess, ftWrite;  
    if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) {  
        std::cout << "Creation time: ";  
        PrintFileTime(ftCreate);  
        std::cout << "Last access time: ";  
        PrintFileTime(ftAccess);  
        std::cout << "Last write time: ";  
        PrintFileTime(ftWrite);  
    } else {  
        std::cerr << "GetFileTime failed." << std::endl;  
    }  
  
    CloseHandle(hFile);  
    return 0;  
}


(7)使用时的注意事项

  1. 确保在调用GetFileTime之前,文件或目录句柄是有效的,并且已经通过CreateFile或其他相关函数打开。
  2. 返回值应该被检查以确保函数成功执行。如果函数失败,可以调用GetLastError获取扩展的错误信息。
  3. 如果需要将FILETIME结构转换为本地时间,可以使用FileTimeToLocalFileTime和FileTimeToSystemTime函数,并可能使用put_time(在C++中)来格式化输出。
  4. 句柄在使用完毕后应该使用CloseHandle函数关闭,以释放系统资源。
  5. 在多线程环境中,需要注意对句柄的同步访问,以避免竞态条件。
  6. 在处理文件路径时

3.27 函数名:GetFileType


(1)函数的概述
GetFileType 是一个Windows API函数,用于确定指定文件或设备的类型。它可以用来检测文件是磁盘文件、磁盘驱动器、字符设备、管道还是未知类型。

(2)函数所在的动态链接库
GetFileType 函数通常位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetFileType(  
  HANDLE hFile  
);


(4)各参数及返回值的详细解释

  • hFile:这是一个打开的文件的句柄,或者是一个设备的句柄。它必须是一个有效的句柄,并且具有FILE_READ_ATTRIBUTES访问权限。
  • 返回值:
  • FILE_TYPE_UNKNOWN (0x0000):文件类型未知。
  • FILE_TYPE_DISK (0x0001):文件在磁盘上。
  • FILE_TYPE_CHAR (0x0002):文件是一个字符设备,如控制台或串口。
  • FILE_TYPE_PIPE (0x0003):文件是一个命名管道。
  • FILE_TYPE_REMOTE (0x8000):这是一个远程文件。此值通常与上述类型之一组合使用,如 FILE_TYPE_REMOTE | FILE_TYPE_DISK。

(5)函数的详细作用
GetFileType 函数用于确定文件或设备的类型。这对于需要区分不同文件类型的应用程序或系统服务非常有用。例如,一个备份软件可能需要知道一个文件是否是一个磁盘文件,以便决定如何备份它。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFileA("C:\\example.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "Failed to open file." << std::endl;  
        return 1;  
    }  
  
    DWORD fileType = GetFileType(hFile);  
    switch (fileType) {  
    case FILE_TYPE_DISK:  
        std::cout << "The file is a disk file." << std::endl;  
        break;  
    case FILE_TYPE_CHAR:  
        std::cout << "The file is a character device." << std::endl;  
        break;  
    case FILE_TYPE_PIPE:  
        std::cout << "The file is a named pipe." << std::endl;  
        break;  
    case FILE_TYPE_UNKNOWN:  
    default:  
        std::cout << "The file type is unknown." << std::endl;  
        break;  
    }  
  
    CloseHandle(hFile);  
    return 0;  
}


(7)使用时的注意事项

  1. 确保提供的句柄是有效的,并且具有适当的访问权限。
  2. 在使用完句柄后,应使用CloseHandle函数关闭它。
  3. 在调用GetFileType之前,不需要检查句柄是否指向一个存在的文件或设备,因为该函数可以处理不存在的句柄(在这种情况下,它可能会返回FILE_TYPE_UNKNOWN)。
  4. 由于这是一个Windows API函数,它只适用于Windows操作系统。在其他操作系统上,这个函数不可用。

3.28 函数名:GetFileVersionInfo


(1)函数的概述
GetFileVersionInfo 是一个Windows API函数,用于检索有关文件版本信息的详细数据。它提供了关于二进制文件(如DLL、EXE、OCX等)的版本信息,这些信息通常用于软件分发、安装和更新。

(2)函数所在的动态链接库
GetFileVersionInfo 函数通常位于 Version.dll 动态链接库中。

(3)函数的原型
 

BOOL GetFileVersionInfo(  
  LPCTSTR lptstrFilename,  
  DWORD   dwHandle,  
  DWORD   dwLen,  
  void    *lpData  
);


(4)各参数及返回值的详细解释

  • lptstrFilename:指向要检索版本信息的文件的完整路径的字符串的指针。
  • dwHandle:这个参数在调用GetFileVersionInfo时通常被设置为0,除非你想从之前由GetFileVersionInfoSize函数返回的缓冲区中检索信息。
  • dwLen:lpData缓冲区的大小(以字节为单位)。
  • lpData:指向接收版本信息数据的缓冲区的指针。这个缓冲区的大小应该由GetFileVersionInfoSize函数确定。
  • 返回值:
  • 如果函数成功,返回值为非零。
  • 如果函数失败,返回值为0。要获取更多错误信息,可以调用GetLastError。

(5)函数的详细作用
GetFileVersionInfo函数用于检索指定文件的版本信息。这些信息通常包括文件的主要版本、次要版本、构建号和修订号,以及可能的其他字符串信息,如公司名称、产品名称、文件描述等。这些信息通常被存储在文件的资源部分,并遵循特定的版本信息格式。

(6)函数的C++示例


#include <windows.h>  
#include <verrsrc.h>  
#include <stdio.h>  
  
#pragma comment(lib, "version.lib")  
  
int main() {  
    const char* filePath = "C:\\example.exe";  
    DWORD dwHandle = 0;  
    DWORD dwInfoSize = GetFileVersionInfoSize(filePath, &dwHandle);  
    if (dwInfoSize == 0) {  
        printf("Failed to get file version info size.\n");  
        return 1;  
    }  
  
    void* pVersionInfo = malloc(dwInfoSize);  
    if (!GetFileVersionInfo(filePath, dwHandle, dwInfoSize, pVersionInfo)) {  
        printf("Failed to get file version info.\n");  
        free(pVersionInfo);  
        return 1;  
    }  
  
    // 这里可以添加代码来解析pVersionInfo缓冲区中的版本信息  
    // ...  
  
    free(pVersionInfo);  
    return 0;  
}  

 
// 注意:上面的示例只演示了如何获取版本信息的大小并分配缓冲区,  
// 但没有展示如何解析版本信息。这通常需要调用VerQueryValue函数。
(7)使用时的注意事项

  1. 确保filePath指向的文件存在且可访问。
  2. 在调用GetFileVersionInfo之前,使用GetFileVersionInfoSize函数确定缓冲区的大小,以避免缓冲区溢出。
  3. 在使用完pVersionInfo缓冲区后,记得释放它。
  4. 如果文件没有版本信息或版本信息格式不正确,GetFileVersionInfo可能会失败。
  5. 如果你需要解析版本信息,你可能需要使用VerQueryValue函数来从pVersionInfo缓冲区中提取所需的数据。
  6. 由于这是一个Windows API函数,它只适用于Windows操作系统。在其他操作系统上,这个函数不可用。

3.29 函数名:GetFileVersionInfoSize


(1)函数的概述
GetFileVersionInfoSize 是一个Windows API函数,用于确定为了包含文件的版本信息,需要为GetFileVersionInfo函数分配多大的缓冲区。这个函数为调用者提供了一个预先确定缓冲区大小的方法,从而可以确保有足够的空间来接收版本信息。

(2)函数所在的动态链接库
GetFileVersionInfoSize 函数通常位于 Version.dll 动态链接库中。

(3)函数的原型

DWORD GetFileVersionInfoSize(  
  LPCTSTR lptstrFilename,  
  LPDWORD lpdwHandle  
);


(4)各参数及返回值的详细解释

  • lptstrFilename:
  • 类型:LPCTSTR(一个指向常量字符串的指针,可以是ANSI或Unicode字符串)
  • 描述:指向要检索版本信息的文件的完整路径的字符串的指针。
  • lpdwHandle:
  • 类型:LPDWORD(指向DWORD的指针)
  • 描述:此参数在调用GetFileVersionInfoSize时通常被设置为NULL。如果此参数不是NULL,它将接收一个句柄,该句柄可用于后续的GetFileVersionInfo调用(但这通常不是必需的)。
  • 返回值:
  • 类型:DWORD
  • 描述:返回为了包含文件的版本信息所需的缓冲区大小(以字节为单位)。如果函数失败,返回值为0。要获取更多错误信息,可以调用GetLastError。

(5)函数的详细作用
GetFileVersionInfoSize 函数的作用是确定为了检索特定文件的版本信息,需要为GetFileVersionInfo函数分配多大的缓冲区。这是因为在某些情况下,文件的版本信息可能非常大,因此预先确定所需的大小可以避免缓冲区溢出。

(6)函数的C++示例


#include <windows.h>  
#include <stdio.h>  
  
#pragma comment(lib, "version.lib")  
  
int main() {  
    const char* filePath = "C:\\example.exe";  
    DWORD dwHandle = 0; // 在此示例中,我们不需要句柄,因此将其设置为0  
    DWORD dwInfoSize = GetFileVersionInfoSize(filePath, &dwHandle);  
    if (dwInfoSize == 0) {  
        DWORD dwError = GetLastError();  
        printf("Failed to get file version info size. Error code: %lu\n", dwError);  
        return 1;  
    }  
  
    // 现在,我们可以为GetFileVersionInfo分配一个足够大的缓冲区  
    void* pVersionInfo = malloc(dwInfoSize);  
    if (pVersionInfo == NULL) {  
        printf("Failed to allocate memory for file version info.\n");  
        return 1;  
    }  
  
    // 接下来,你可以使用GetFileVersionInfo来检索版本信息  
    // ...  
  
    // 释放内存  
    free(pVersionInfo);  
  
    return 0;  
}


(7)使用时的注意事项

  1. 确保filePath指向的文件存在且可访问。
  2. lpdwHandle参数在大多数情况下可以设置为NULL,除非你打算在后续的GetFileVersionInfo调用中使用这个句柄。
  3. 在使用malloc分配内存后,确保在不再需要时释放它,以避免内存泄漏。
  4. 如果GetFileVersionInfoSize返回0,表示函数失败,此时应该调用GetLastError来获取更详细的错误信息。
  5. 文件的版本信息可能不存在或格式不正确,这可能导致GetFileVersionInfoSize失败。
  6. 由于这是一个Windows API函数,它只适用于Windows操作系统。在其他操作系统上,这个函数不可用。

3.30 函数名:GetFullPathName


(1)函数的概述
GetFullPathName 是一个Windows API函数,它用于检索指定文件或目录的完整路径名。这个函数会解析任何路径中的相对路径部分(如.、..)和符号链接,并返回包含绝对路径的字符串。

(2)函数所在的动态链接库
GetFullPathName 函数通常位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetFullPathName(  
  LPCTSTR lpFileName,  
  LPDWORD lpnBufferLength,  
  LPTSTR  lpBuffer,  
  LPTSTR  *lpFilePart  
);


(4)各参数及返回值的详细解释

  • lpFileName:
  • 类型:LPCTSTR(指向常量字符串的指针)
  • 描述:指定要检索其完整路径名的文件或目录的名称。这个名称可以是相对路径或绝对路径。
  • lpnBufferLength:
  • 类型:LPDWORD(指向DWORD的指针)
  • 描述:在调用时,这个参数应该指向一个变量,该变量包含lpBuffer缓冲区的大小(以TCHAR为单位)。如果函数成功,这个变量将被设置为返回的完整路径名的长度(不包括终止的空字符)。
  • lpBuffer:
  • 类型:LPTSTR(指向TCHAR字符串的指针)
  • 描述:指向一个缓冲区,该缓冲区接收文件或目录的完整路径名。如果缓冲区太小而无法容纳完整路径名,则路径名将被截断,但总是以空字符结尾。
  • lpFilePart:
  • 类型:LPTSTR *(指向LPTSTR的指针)
  • 描述:如果此参数不为NULL,它将接收指向lpBuffer中完整路径名中最后一个组成部分(即文件名或目录名)的指针。这通常用于在路径和文件名之间分隔字符串。
  • 返回值:
  • 类型:DWORD
  • 描述:如果函数成功,返回值是完整路径名的长度(以TCHAR为单位),不包括终止的空字符。如果缓冲区太小,无法容纳完整的路径和终止的空字符,返回值是所需的缓冲区大小,包括终止的空字符。如果函数失败,返回值是0。要获取更多错误信息,可以调用GetLastError。

(5)函数的详细作用
GetFullPathName 的主要作用是获取指定文件或目录的完整路径名。这在处理相对路径、符号链接或需要确定文件或目录的确切位置时非常有用。它还可以用来检查路径是否存在或验证路径的语法是否正确。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* filePath = "..\\example.txt"; // 相对路径  
    DWORD dwBufferSize = MAX_PATH; // 假设缓冲区足够大以容纳完整路径  
    char buffer[MAX_PATH];  
    char* filePart;  
  
    DWORD result = GetFullPathName(filePath, &dwBufferSize, buffer, &filePart);  
    if (result == 0) {  
        std::cerr << "GetFullPathName failed with error: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    std::cout << "Full path: " << buffer << std::endl;  
    std::cout << "File part: " << filePart << std::endl;  
  
    return 0;  
}


(7)使用时的注意事项

  1. 确保lpBuffer缓冲区足够大,以容纳完整的路径名和终止的空字符。否则,路径名可能会被截断。
  2. 调用GetFullPathName后,应检查返回值以确定是否成功,以及是否需要更大的缓冲区。
  3. 如果lpFilePart参数不为NULL,则可以使用返回的指针来分隔路径和文件名。
  4. 如果指定的文件或目录不存在,GetFullPathName仍然会返回解析后的路径,但文件或目录的存在性需要由其他函数(如GetFileAttributes)来验证。
  5. 在处理跨平台代码时,请注意GetFullPathName是Windows特有的API,不适用于非Windows操作系统。

3.31 函数名:GetLogicalDrives


(1)函数的概述
GetLogicalDrives 是一个Windows API函数,用于检索当前系统上的逻辑磁盘驱动器。它返回一个位掩码,其中每个位代表一个有效的逻辑驱动器。

(2)函数所在的动态链接库
这个函数位于kernel32.dll中。

(3)函数的原型

DWORD GetLogicalDrives(void);


(4)各参数及返回值的详细解释

  • 参数:此函数没有参数。
  • 返回值:返回一个DWORD值,这是一个32位无符号整数。每一位代表一个逻辑驱动器。位0(最低位)代表驱动器A,位1代表驱动器B,依此类推,直到位25(第26个位)代表驱动器Z。如果某个位被设置(即值为1),则表示相应的逻辑驱动器存在。

(5)函数的详细作用
GetLogicalDrives 函数的主要作用是检测并返回系统上所有逻辑驱动器的位掩码。这可以用于枚举所有存在的逻辑驱动器,或者检查特定的逻辑驱动器是否存在。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    DWORD drives = GetLogicalDrives();  
  
    char driveLetters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 26个驱动器加上终止符  
    for (int i = 0; i < 26; ++i) {  
        if (drives & (1 << i)) { // 检查第i位是否被设置  
            std::cout << "Drive " << driveLetters[i] << " exists." << std::endl;  
        }  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 确保在包含windows.h之前定义了WIN32_LEAN_AND_MEAN或NOGDI等宏,以避免不必要的头文件和符号被包含。
  2. 由于这个函数返回的是位掩码,所以在检查某个驱动器是否存在时,需要正确地使用位操作。
  3. 这个函数只能告诉你哪些逻辑驱动器存在,但并不能告诉你这些驱动器的类型(如硬盘、USB驱动器、网络驱动器等)或它们的具体信息(如总大小、可用空间等)。
  4. 由于这个函数返回的是逻辑驱动器,而不是物理驱动器,因此可能存在多个逻辑驱动器映射到同一个物理驱动器的情况(例如,通过分区)。
  5. 在调用此函数之前,最好检查是否成功加载了kernel32.dll。虽然这通常不是问题,但在某些特殊情况下(如自定义操作系统或受限环境)可能是必要的。

3.32 函数名:GetLogicalDriveStrings


(1)函数的概述
GetLogicalDriveStrings 是一个Windows API函数,用于检索当前系统上所有逻辑磁盘驱动器的字符串。这个函数返回一个以空字符('\0')分隔的双字节字符串数组,其中每个字符串代表一个逻辑驱动器的根目录路径(例如 "C:")。

(2)函数所在的动态链接库
这个函数位于kernel32.dll中。

(3)函数的原型

DWORD GetLogicalDriveStrings(  
  DWORD   nBufferLength,  
  LPTSTR  lpBuffer  
);


(4)各参数及返回值的详细解释

  • nBufferLength:指定lpBuffer缓冲区的长度(以TCHAR为单位)。此值应该足够大,以容纳所有逻辑驱动器的字符串加上终止的空字符。
  • lpBuffer:指向接收逻辑驱动器字符串的缓冲区的指针。缓冲区必须足够大,以容纳所有逻辑驱动器的字符串加上终止的空字符。
  • 返回值:如果函数成功,返回值是复制到缓冲区的字符数(不包括终止的空字符)。如果缓冲区太小,无法容纳所有逻辑驱动器的字符串,返回值是需要的缓冲区大小(包括终止的空字符)。如果函数失败,返回值是0。要获取扩展的错误信息,可以调用GetLastError。
  • (5)函数的详细作用
  • GetLogicalDriveStrings函数的主要作用是检索当前系统上所有逻辑驱动器的根目录路径。这些路径以空字符分隔的双字节字符串数组的形式返回。这个数组以两个空字符('\0\0')结尾,以标记字符串数组的结束。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
#include <tchar.h>  
  
int main() {  
    // 假设最大有32个驱动器(A: 到 Z:),每个驱动器名最多为4个字符(例如 "C:\"),加上空字符分隔和结尾的双空字符  
    TCHAR buffer[32 * 4 + 2 * (32 - 1) + 2]; // 缓冲区大小足够大  
    DWORD result = GetLogicalDriveStrings(sizeof(buffer) / sizeof(TCHAR), buffer);  
  
    if (result > 0 && result <= sizeof(buffer) / sizeof(TCHAR)) {  
        // 遍历返回的字符串数组  
        for (TCHAR* p = buffer; *p != _T('\0'); p += _tcslen(p) + 1) {  
            std::wcout << p << std::endl; // 假设使用宽字符版本,输出逻辑驱动器路径  
        }  
    } else {  
        // 处理错误  
        std::cerr << "Failed to get logical drive strings. Error: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}

(7)使用时的注意事项

  1. 调用GetLogicalDriveStrings时,确保提供的缓冲区足够大,以容纳所有逻辑驱动器的字符串。否则,函数将失败,并返回需要的缓冲区大小。
  2. 如果函数成功,但返回的字符数等于提供的缓冲区大小(不包括终止的空字符),那么缓冲区可能没有完全填充,因为最后一个字符串可能被截断了。
  3. 由于返回的是双字节字符串(在Unicode版本中为宽字符字符串),因此在使用字符串函数(如strlen)时,应该使用相应的双字节版本(如_tcslen)。
  4. 在处理返回的字符串时,请注意字符串是以空字符分隔的,并且以两个空字符结尾。
  5. 确保在调用此函数之前,程序已经成功加载了kernel32.dll。这通常在Windows应用程序中是默认的,但在某些特殊情况下可能需要额外注意。

3.33 函数名:GetOverlappedResult


(1)函数的概述
GetOverlappedResult 是一个Windows API函数,用于获取重叠I/O操作的结果。重叠I/O是一种允许应用程序在等待I/O操作完成的同时执行其他操作的机制。GetOverlappedResult 可以检索一个重叠I/O操作的状态,包括操作是否完成、传输的字节数以及是否发生错误。

(2)函数所在的动态链接库
这个函数位于kernel32.dll中。

(3)函数的原型

BOOL GetOverlappedResult(  
  HANDLE   hFile,  
  LPOVERLAPPED lpOverlapped,  
  LPDWORD  lpNumberOfBytesTransferred,  
  BOOL     bWait  
);


(4)各参数及返回值的详细解释

  • hFile:指定一个打开的文件或I/O设备的句柄,该句柄必须与重叠I/O操作相关联。
  • lpOverlapped:指向一个OVERLAPPED结构的指针,该结构包含了重叠I/O操作的信息。
  • lpNumberOfBytesTransferred:指向一个DWORD变量的指针,该变量接收重叠I/O操作传输的字节数。
  • bWait:如果此参数为TRUE,则函数将等待重叠I/O操作完成。如果此参数为FALSE并且操作尚未完成,则函数将立即返回FALSE,并且可以通过调用GetLastError来获取ERROR_IO_INCOMPLETE错误。
  • 返回值:如果函数成功,则返回值为非零。如果函数失败,则返回值为零。要获取扩展的错误信息,可以调用GetLastError。

(5)函数的详细作用
GetOverlappedResult函数用于检索与指定文件或I/O设备句柄相关联的重叠I/O操作的结果。如果bWait参数为TRUE,则函数将等待操作完成并返回结果。如果bWait参数为FALSE,则函数将立即返回操作的状态,而不会等待其完成。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFile(  
        TEXT("example.txt"),             // 文件名  
        GENERIC_WRITE,                   // 打开以写入  
        0,                               // 不共享  
        NULL,                            // 默认安全  
        OPEN_ALWAYS,                     // 打开或创建  
        FILE_ATTRIBUTE_NORMAL,            // 正常文件  
        NULL                             // 不使用模板文件  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "CreateFile failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    OVERLAPPED overlapped = { 0 };  
    DWORD bytesWritten = 0;  
    BOOL result = WriteFileEx(  
        hFile,  
        "Hello, World!",       // 要写入的数据  
        13,                    // 数据的大小  
        &overlapped,           // 重叠结构  
        NULL                   // 不使用完成例程  
    );  
  
    if (!result) {  
        std::cerr << "WriteFileEx failed: " << GetLastError() << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    // 等待操作完成并获取结果  
    result = GetOverlappedResult(hFile, &overlapped, &bytesWritten, TRUE);  
    if (!result) {  
        std::cerr << "GetOverlappedResult failed: " << GetLastError() << std::endl;  
    } else {  
        std::cout << "Bytes written: " << bytesWritten << std::endl;  
    }  
  
    CloseHandle(hFile);  
    return 0;  
}


(7)使用时的注意事项

  1. 在调用GetOverlappedResult之前,必须确保已经通过CreateFile或类似的函数打开了文件或I/O设备,并且句柄与重叠I/O操作相关联。
  2. OVERLAPPED结构必须在使用之前正确初始化,特别是在多线程环境中,以避免潜在的竞争条件。
  3. 如果bWait参数为FALSE并且重叠I/O操作尚未完成,GetOverlappedResult将返回FALSE,并且GetLastError将返回ERROR_IO_INCOMPLETE。在这种情况下,可以稍后再次调用GetOverlappedResult来检查操作的状态。
  4. 如果重叠I/O操作已经完成,但发生了错误,GetOverlappedResult将返回FALSE,并且可以通过调用GetLastError来获取具体的

3.34 函数名:GetPrivateProfileInt


(1)函数的概述
GetPrivateProfileInt 是一个Windows API函数,用于从初始化文件(.ini文件)中读取一个整数值。这些文件通常用于存储应用程序的配置信息。

(2)函数所在的动态链接库
GetPrivateProfileInt 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

UINT GetPrivateProfileInt(  
  LPCTSTR lpAppName,  
  LPCTSTR lpKeyName,  
  INT     nDefault,  
  LPCTSTR lpFileName  
);


(4)各参数及返回值的详细解释

  • lpAppName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索值的节(section)的名称。
  • lpKeyName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索值的键(key)的名称。
  • nDefault:如果指定的键在指定的节中不存在,则返回此默认值。
  • lpFileName:指向初始化文件名的以null结尾的字符串的指针。如果此参数为NULL,则函数将搜索Windows目录中的WIN.INI文件。
  • 返回值:
  • 函数返回指定键的值。如果键不存在或指定的节不存在,则返回nDefault参数指定的值。

(5)函数的详细作用
GetPrivateProfileInt 函数用于从指定的初始化文件中读取一个整数值。它首先查找指定的节和键,如果找到,则返回与该键关联的值(作为整数)。如果节或键不存在,则返回默认值。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* fileName = "example.ini";  
    const char* section = "Settings";  
    const char* key = "Value";  
    int defaultValue = 0;  
  
    int value = GetPrivateProfileInt(section, key, defaultValue, fileName);  
    std::cout << "Value from INI file: " << value << std::endl;  
  
    return 0;  
}


(7)使用时的注意事项

  1. 文件路径:确保lpFileName参数指向的文件存在且可访问。
  2. 错误处理:虽然GetPrivateProfileInt没有直接的错误返回值,但你可以通过检查返回值是否与默认值相同来推断是否发生了某种问题(例如,键或节不存在)。
  3. 线程安全:在多线程环境中,如果多个线程同时访问同一个初始化文件,可能会导致数据不一致。确保适当的同步机制。
  4. 替代方案:对于更复杂的配置管理需求,考虑使用XML、JSON或其他现代格式,并使用相应的解析库。
  5. 性能:频繁地读取和写入INI文件可能会影响性能。对于需要高性能配置管理的应用程序,请考虑其他解决方案。

3.35 函数名:GetPrivateProfileSection


(1)函数的概述
GetPrivateProfileSection 是一个Windows API函数,它用于从指定的初始化文件(.ini文件)中检索指定节(section)的所有键(key)和值(value),并将它们存储在一个由调用者提供的缓冲区中。

(2)函数所在的动态链接库
GetPrivateProfileSection 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetPrivateProfileSection(  
  LPCTSTR lpAppName,  
  LPTSTR  lpReturnedString,  
  DWORD   nSize,  
  LPCTSTR lpFileName  
);


(4)各参数及返回值的详细解释

  • lpAppName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索数据的节(section)的名称。如果此参数为NULL,则函数将检索指定文件中的所有节。
  • lpReturnedString:指向一个缓冲区的指针,该缓冲区用于接收从指定的初始化文件中检索到的节内容。
  • nSize:指定lpReturnedString缓冲区的大小(以TCHAR为单位)。如果节的内容超过了缓冲区的大小,则缓冲区中的字符串将被截断。
  • lpFileName:指向初始化文件名的以null结尾的字符串的指针。如果此参数为NULL,则函数将搜索Windows目录中的WIN.INI文件。
  • 返回值:
  • 如果函数成功,返回值是复制到缓冲区的字符数(不包括终止的null字符)。如果指定的节不存在,则返回0。如果缓冲区太小,无法包含整个节的内容,则返回缓冲区的大小(不包括终止的null字符),并设置全局变量GetLastError为ERROR_MORE_DATA。
  • (5)函数的详细作用
  • GetPrivateProfileSection 函数用于从指定的初始化文件中检索一个节的所有键和值,并将它们作为一个字符串存储在提供的缓冲区中。这个字符串的格式是key=value\0key=value\0...\0\0,其中\0是null字符,用作键/值对的分隔符和字符串的终止符。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* fileName = "example.ini";  
    const char* section = "Settings";  
    char buffer[1024]; // 假设缓冲区足够大以容纳整个节的内容  
    DWORD result;  
  
    result = GetPrivateProfileSection(section, buffer, sizeof(buffer), fileName);  
    if (result > 0 && result < sizeof(buffer)) {  
        std::cout << "Section contents:\n" << buffer << std::endl;  
    } else if (result == sizeof(buffer)) {  
        std::cerr << "Buffer too small to hold the entire section." << std::endl;  
    } else {  
        std::cerr << "Section not found or other error occurred." << std::endl;  
    }  
  
    return 0;  
}


(7)使用时的注意事项

  1. 缓冲区大小:确保lpReturnedString缓冲区足够大,以容纳整个节的内容,包括额外的null终止符。如果缓冲区太小,则数据可能会被截断,并且函数将返回ERROR_MORE_DATA。
  2. 错误处理:检查返回值以确定是否成功检索了节的内容。如果返回值为sizeof(buffer),则表示缓冲区太小。可以使用GetLastError函数来获取更详细的错误信息。
  3. 字符串解析:由于GetPrivateProfileSection返回的字符串包含null字符作为分隔符,因此在解析此字符串时需要特别小心,以避免访问越界或未初始化的内存。
  4. 线程安全:在多线程环境中,如果多个线程同时访问同一个初始化文件,可能会导致数据不一致。确保适当的同步机制。
  5. 文件路径:确保lpFileName参数指向的文件存在且可访问。如果文件不存在或无法访问,则函数将失败。
  6. 性能:频繁地读取和写入INI文件可能会影响性能。对于需要高性能配置管理的应用程序,请考虑使用其他配置文件格式和解析库。

3.36 函数名:GetPrivateProfileString


(1)函数的概述
GetPrivateProfileString 是一个Windows API函数,用于从指定的初始化文件(.ini文件)中检索指定节(section)下的指定键(key)的值(value),并将该值复制到由调用者提供的缓冲区中。

(2)函数所在的动态链接库
GetPrivateProfileString 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetPrivateProfileString(  
  LPCTSTR lpAppName,  
  LPCTSTR lpKeyName,  
  LPCTSTR lpDefault,  
  LPTSTR  lpReturnedString,  
  DWORD   nSize,  
  LPCTSTR lpFileName  
);


(4)各参数及返回值的详细解释

  • lpAppName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索值的节(section)的名称。
  • lpKeyName:指向一个以null结尾的字符串的指针,该字符串指定了要检索其值的键(key)的名称。
  • lpDefault:如果指定的键在指定的节中不存在,则此参数指向的字符串将被复制到lpReturnedString所指向的缓冲区中。
  • lpReturnedString:指向一个缓冲区的指针,该缓冲区用于接收从指定的初始化文件中检索到的键的值。
  • nSize:指定lpReturnedString缓冲区的大小(以TCHAR为单位)。如果键的值超过了缓冲区的大小,则缓冲区中的字符串将被截断。
  • lpFileName:指向初始化文件名的以null结尾的字符串的指针。如果此参数为NULL,则函数将搜索Windows目录中的WIN.INI文件。
  • 返回值:
  • 如果函数成功,返回值是复制到缓冲区的字符数(不包括终止的null字符)。如果指定的键不存在,则返回0。如果缓冲区太小,无法包含整个键的值,则返回缓冲区的大小(不包括终止的null字符),并设置全局变量GetLastError为ERROR_MORE_DATA。
  • (5)函数的详细作用
  • GetPrivateProfileString 函数用于从指定的初始化文件中检索一个键的值,并将该值复制到提供的缓冲区中。如果键不存在,则可以将一个默认值复制到缓冲区中。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* fileName = "example.ini";  
    const char* section = "Settings";  
    const char* key = "MyKey";  
    const char* defaultValue = "DefaultValue";  
    char buffer[256];  
    DWORD result;  
  
    result = GetPrivateProfileString(section, key, defaultValue, buffer, sizeof(buffer), fileName);  
    if (result > 0 && result < sizeof(buffer)) {  
        std::cout << "Value for key '" << key << "': " << buffer << std::endl;  
    } else if (result == sizeof(buffer) - 1) { // 减去1,因为需要为null终止符留出空间  
        std::cerr << "Buffer too small to hold the entire value." << std::endl;  
    } else {  
        std::cerr << "Key not found or other error occurred. Using default value: " << defaultValue << std::endl;  
        // 在这里可以使用defaultValue作为备选值  
    }  
  
    return 0;  
}


(7)使用时的注意事项

  1. 缓冲区大小:确保lpReturnedString缓冲区足够大,以容纳键的值,包括额外的null终止符。如果缓冲区太小,则数据可能会被截断,并且函数将返回ERROR_MORE_DATA。
  2. 错误处理:检查返回值以确定是否成功检索了键的值。如果返回值为sizeof(buffer) - 1(考虑到null终止符),则表示缓冲区太小。可以使用GetLastError函数来获取更详细的错误信息。
  3. 字符串解析:由于GetPrivateProfileString返回的字符串以null字符结尾,因此在解析此字符串时不需要担心字符串越界。
  4. 线程安全:在多线程环境中,如果多个线程同时访问同一个初始化文件,可能会导致数据不一致。确保适当的同步机制。
  5. 文件路径:确保lpFileName参数指向的文件存在且可访问。如果文件不存在或无法访问,则函数将失败。
  6. 性能:频繁地读取和写入INI文件可能会影响性能。对于需要高性能配置管理的应用程序,请考虑使用其他配置文件格式和解析库。
  7. 编码:如果INI文件使用非ASCII编码(如UTF-8),则需要注意字符编码的转换和兼容性。

3.37 函数名:GetProfileInt


(1)函数的概述
GetProfileInt 是一个Windows API函数,用于从指定的初始化文件(.ini文件)中检索指定节(section)下的指定键(key)的整数值。如果键不存在或无法转换为整数,则返回一个默认值。

(2)函数所在的动态链接库
GetProfileInt 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

UINT GetProfileInt(  
  LPCTSTR lpAppName,  
  LPCTSTR lpKeyName,  
  INT     nDefault  
);


(4)各参数及返回值的详细解释

  • lpAppName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索值的节(section)的名称。
  • lpKeyName:指向一个以null结尾的字符串的指针,该字符串指定了要检索其值的键(key)的名称。
  • nDefault:如果指定的键在指定的节中不存在,或者键的值不是有效的整数,则此参数指定的值将被返回。
  • 返回值:
  • 如果函数成功,返回值是指定的键对应的整数值。如果键不存在或无法转换为整数,则返回nDefault参数指定的值。

(5)函数的详细作用
GetProfileInt 函数尝试从指定的初始化文件中读取指定节和键下的字符串值,并将其转换为一个整数。如果无法读取键的值,或者该值不是一个有效的整数,则函数返回nDefault参数指定的默认值。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* fileName = "example.ini"; // 注意:GetProfileInt不直接接受文件名,它使用默认的WIN.INI或应用程序的.INI文件  
    const char* section = "Settings";  
    const char* key = "MyIntegerKey";  
    int defaultValue = 123;  
  
    int result = GetProfileInt(section, key, defaultValue);  
    std::cout << "Value for key '" << key << "': " << result << std::endl;  
  
    return 0;  
}


注意:在上面的示例中,GetProfileInt 实际上不会直接读取fileName指定的文件,因为它默认读取WIN.INI或应用程序的.INI文件(如果存在)。如果你需要读取特定文件,应使用GetPrivateProfileInt函数。

(7)使用时的注意事项

  1. 默认行为:GetProfileInt 默认读取WIN.INI文件或应用程序的.INI文件(如果存在)。如果你需要读取其他文件,请使用GetPrivateProfileInt。
  2. 错误处理:由于GetProfileInt没有提供直接的错误代码,你需要通过返回值来判断是否使用了默认值。如果返回值等于nDefault,则可能表示键不存在或值无法转换为整数。
  3. 整数转换:确保INI文件中键的值是可以转换为整数的字符串。如果值包含非数字字符,则函数将返回默认值。
  4. 线程安全:在多线程环境中,如果多个线程同时访问同一个初始化文件,可能会导致数据不一致。确保适当的同步机制。
  5. 性能:频繁地读取和写入INI文件可能会影响性能。对于需要高性能配置管理的应用程序,请考虑使用其他配置文件格式和解析库。
  6. 文件路径:由于GetProfileInt不直接接受文件路径,因此无需担心文件路径的问题。但是,如果你使用GetPrivateProfileInt,则需要确保文件路径正确且文件可访问。
  7. 编码:如果INI文件使用非ASCII编码(如UTF-8),则需要注意字符编码的转换和兼容性。尽管GetProfileInt主要关注整数值,但键的名称可能仍会受到编码问题的影响。

3.38 函数名:GetProfileSection


(1)函数的概述
GetProfileSection 是一个Windows API函数,用于从指定的初始化文件(.ini文件)中检索指定节(section)的所有键和值,并将它们复制到由调用者提供的缓冲区中。

(2)函数所在的动态链接库
GetProfileSection 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetProfileSection(  
  LPCTSTR lpAppName,  
  LPTSTR  lpReturnedString,  
  DWORD   nSize  
);


(4)各参数及返回值的详细解释

  • lpAppName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索键和值的节(section)的名称。
  • lpReturnedString:指向一个缓冲区的指针,该缓冲区用于接收从指定的初始化文件中检索到的节的所有键和值。键和值对将被写入缓冲区,每个键和值对之间由null字符分隔,而节的末尾由两个null字符表示。
  • nSize:指定lpReturnedString缓冲区的大小(以TCHAR为单位)。如果节的内容超过了缓冲区的大小,则缓冲区中的字符串将被截断。
  • 返回值:
  • 如果函数成功,返回值是复制到缓冲区的字符数(不包括终止的双null字符)。如果指定的节不存在,则返回0。如果缓冲区太小,无法包含整个节的内容,则返回缓冲区的大小(不包括终止的双null字符),并设置全局变量GetLastError为ERROR_MORE_DATA。

(5)函数的详细作用
GetProfileSection 函数用于从指定的初始化文件中检索一个完整节的内容,并将这些内容复制到提供的缓冲区中。如果节不存在,则不会向缓冲区中写入任何内容。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* section = "Settings";  
    char buffer[1024]; // 假设缓冲区足够大以容纳整个节的内容  
    DWORD result;  
  
    result = GetProfileSection(section, buffer, sizeof(buffer));  
    if (result > 0 && result < sizeof(buffer) - 1) { // 减去1以确保有足够的空间容纳终止的双null字符  
        std::cout << "Contents of section '" << section << "':\n" << buffer << std::endl;  
    } else if (result == sizeof(buffer) - 2) { // 减去2以考虑终止的双null字符  
        std::cerr << "Buffer too small to hold the entire section." << std::endl;  
    } else {  
        std::cerr << "Section not found or other error occurred." << std::endl;  
    }  
  
    return 0;  
}

注意:在输出buffer的内容时,你可能需要添加一些额外的逻辑来正确显示null字符分隔的键和值对。

(7)使用时的注意事项

  1. 缓冲区大小:确保lpReturnedString缓冲区足够大,以容纳节的所有内容,包括额外的null字符。如果缓冲区太小,则数据可能会被截断,并且函数将返回ERROR_MORE_DATA。
  2. 错误处理:检查返回值以确定是否成功检索了节的内容。如果返回值为sizeof(buffer) - 2(考虑到终止的双null字符),则表示缓冲区太小。可以使用GetLastError函数来获取更详细的错误信息。
  3. 字符串解析:由于GetProfileSection返回的字符串由null字符分隔,因此在解析此字符串时需要注意字符串的边界。
  4. 线程安全:在多线程环境中,如果多个线程同时访问同一个初始化文件,可能会导致数据不一致。确保适当的同步机制。
  5. 文件路径:与GetProfileString和GetProfileInt不同,GetProfileSection不会直接接受文件路径作为参数。它默认读取WIN.INI文件或应用程序的.INI文件(如果存在)。如果你需要读取特定文件,应使用GetPrivateProfileSection函数。
  6. 性能:频繁地读取和写入INI文件可能会影响性能。对于需要高性能配置管理的应用程序,请考虑使用其他配置文件格式和解析库。
  7. 编码:如果INI文件使用非ASCII编码(如UTF-8),则需要注意字符编码的转换和兼容性。

3.39 函数名:GetProfileString


(1)函数的概述
GetProfileString 是一个Windows API函数,用于从指定的初始化文件(.ini文件)中检索指定节(section)下的指定键(key)的字符串值。如果键不存在,则返回默认值。

(2)函数所在的动态链接库
GetProfileString 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetProfileString(  
  LPCTSTR lpAppName,  
  LPCTSTR lpKeyName,  
  LPCTSTR lpDefault,  
  LPTSTR  lpReturnedString,  
  DWORD   nSize  
);


(4)各参数及返回值的详细解释

  • lpAppName:指向一个以null结尾的字符串的指针,该字符串指定了要从中检索值的节(section)的名称。
  • lpKeyName:指向一个以null结尾的字符串的指针,该字符串指定了要检索其值的键(key)的名称。
  • lpDefault:如果指定的键在指定的节中不存在,则此参数指定的字符串将被复制到lpReturnedString所指向的缓冲区中,作为默认值。
  • lpReturnedString:指向一个缓冲区的指针,该缓冲区用于接收从指定的初始化文件中检索到的键的值。
  • nSize:指定lpReturnedString缓冲区的大小(以TCHAR为单位)。如果键的值超过了缓冲区的大小,则缓冲区中的字符串将被截断。
  • 返回值:
  • 如果函数成功,返回值是复制到lpReturnedString缓冲区的字符数(不包括终止的null字符)。如果指定的键不存在,则返回值是复制到缓冲区的默认值的字符数(不包括终止的null字符)。如果缓冲区太小,无法包含整个字符串,则返回缓冲区的大小(不包括终止的null字符),并设置全局变量GetLastError为ERROR_MORE_DATA。

(5)函数的详细作用
GetProfileString 函数用于从指定的初始化文件中检索指定节下的指定键的字符串值。如果键不存在,则返回默认值。检索到的值(或默认值)将被复制到提供的缓冲区中。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* fileName = "example.ini"; // 注意:GetProfileString不直接接受文件名,它使用默认的WIN.INI或应用程序的.INI文件  
    const char* section = "Settings";  
    const char* key = "MyStringKey";  
    const char* defaultValue = "DefaultValue";  
    char buffer[256];  
  
    DWORD result = GetProfileString(section, key, defaultValue, buffer, sizeof(buffer));  
    if (result > 0 && result < sizeof(buffer)) {  
        std::cout << "Value for key '" << key << "': " << buffer << std::endl;  
    } else {  
        std::cerr << "Error occurred or buffer was too small." << std::endl;  
    }  
  
    return 0;  
}


注意:在上面的示例中,GetProfileString 实际上不会直接读取fileName指定的文件,它默认读取WIN.INI文件或应用程序的.INI文件(如果存在)。如果你需要读取特定文件,应使用GetPrivateProfileString函数。

(7)使用时的注意事项

  1. 缓冲区大小:确保lpReturnedString缓冲区足够大,以容纳键的值(或默认值),包括额外的null终止字符。如果缓冲区太小,则数据可能会被截断。
  2. 错误处理:检查返回值以确定是否成功检索了键的值。如果返回值等于缓冲区的大小(不包括null终止字符),则表示缓冲区太小,无法容纳整个字符串。可以使用GetLastError函数来获取更详细的错误信息。
  3. 字符串解析:返回的字符串是以null字符终止的,因此不需要担心字符串的边界问题(除非缓冲区太小)。
  4. 线程安全:在多线程环境中,如果多个线程同时访问同一个初始化文件,可能会导致数据不一致。确保适当的同步机制。
  5. 文件路径:与GetProfileInt类似,GetProfileString不直接接受文件路径作为参数。它默认读取WIN.INI文件或应用程序的.INI文件(如果存在)。如果需要读取特定文件,应使用GetPrivateProfileString函数。
  6. 性能:频繁地读取和写入INI文件可能会影响性能。对于需要高性能配置管理的应用程序,请考虑使用其他配置文件格式和解析库。
  7. 编码:如果INI文件使用非ASCII编码(如UTF-8),则需要注意字符编码的转换和兼容性。

3.40 函数名:GetShortPathName


(1)函数的概述
GetShortPathName 是一个Windows API函数,用于获取指定文件或目录的短路径名。在某些情况下,尤其是在旧的Windows系统或不支持长文件名(超过8.3格式)的某些API中,可能需要使用短路径名。

(2)函数所在的动态链接库
GetShortPathName 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

WORD GetShortPathName(  
  LPCTSTR lpszLongPath,  
  LPTSTR  lpszShortPath,  
  DWORD   cchBuffer  
);


(4)各参数及返回值的详细解释

  • lpszLongPath:指向一个以null结尾的字符串的指针,该字符串指定了要转换为其短路径名的文件或目录的路径。
  • lpszShortPath:指向一个缓冲区的指针,该缓冲区用于接收返回的短路径名字符串。
  • cchBuffer:指定lpszShortPath缓冲区的大小(以TCHAR为单位)。
  • 返回值:
  • 如果函数成功,返回值是复制到lpszShortPath缓冲区的字符数(不包括终止的null字符)。如果lpszShortPath缓冲区太小,无法包含整个短路径名,则返回cchBuffer减1(以预留空间给null终止字符),并设置全局变量GetLastError为ERROR_INSUFFICIENT_BUFFER。如果函数失败,则返回值为0。

(5)函数的详细作用
GetShortPathName 函数将指定的长路径名转换为短路径名(8.3格式),并将结果存储在提供的缓冲区中。如果文件或目录没有对应的短路径名(例如,在支持长文件名的系统上),则该函数可能会返回原始的长路径名。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    const char* longPath = "C:\\Program Files\\Example\\LongFileName.txt";  
    char shortPath[MAX_PATH]; // MAX_PATH 是预定义的最大路径长度  
  
    DWORD result = GetShortPathNameA(longPath, shortPath, MAX_PATH);  
    if (result != 0 && result < MAX_PATH) {  
        std::cout << "Short path: " << shortPath << std::endl;  
    } else {  
        std::cerr << "Error occurred or buffer was too small." << std::endl;  
        if (result == 0) {  
            // 获取具体的错误代码  
            DWORD errorCode = GetLastError();  
            std::cerr << "Error code: " << errorCode << std::endl;  
        }  
    }  
  
    return 0;  
}


注意:这里使用了GetShortPathNameA,它是GetShortPathName的ANSI版本。如果你正在处理宽字符(Unicode)字符串,请使用GetShortPathNameW。

(7)使用时的注意事项

  1. 缓冲区大小:确保lpszShortPath缓冲区足够大,以容纳返回的短路径名(包括额外的null终止字符)。如果缓冲区太小,则数据可能会被截断,并且GetLastError将返回ERROR_INSUFFICIENT_BUFFER。
  2. 错误处理:检查返回值以确定是否成功获取了短路径名。如果返回值为0,则使用GetLastError来获取更详细的错误信息。
  3. 长文件名支持:在支持长文件名的系统上,即使调用了GetShortPathName,返回的也可能是原始的长路径名。因此,在调用此函数之前,不要假设一定会得到短路径名。
  4. 线程安全:在多线程环境中,如果多个线程同时调用此函数并访问相同的文件或目录,可能会导致数据竞争或其他同步问题。确保适当的同步机制。
  5. 使用场景:在现代Windows系统上,由于大多数API都支持长文件名,因此使用短路径名的需求可能较少。然而,在某些特定情况下(如与旧API或系统交互时),可能仍然需要短路径名。

3.41 函数名:GetSystemDirectory


(1)函数的概述
GetSystemDirectory 函数是一个Windows API函数,用于检索Windows系统目录(如C:\Windows\System32)的完全限定路径。

(2)函数所在的动态链接库
GetSystemDirectory 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

UINT GetSystemDirectory(  
  LPTSTR lpBuffer,  
  UINT   uSize  
);


(4)各参数及返回值的详细解释

  • lpBuffer:指向一个缓冲区的指针,该缓冲区用于接收系统目录的路径。这个缓冲区的大小应足够大,以存储包括null终止字符在内的系统目录的完全限定路径。
  • uSize:指定lpBuffer缓冲区的大小(以TCHAR为单位)。
  • 返回值:
  • 如果函数成功,返回值是复制到lpBuffer缓冲区中的字符数(不包括终止的null字符)。如果lpBuffer缓冲区太小,无法包含整个系统目录路径,则返回值是所需的缓冲区大小(包括终止的null字符)。如果函数失败,返回值为0。

(5)函数的详细作用
GetSystemDirectory 函数将Windows系统目录的路径复制到指定的缓冲区中。这个路径通常是固定的,如C:\Windows\System32(对于32位Windows系统上的32位应用)或C:\Windows\SysWOW64(对于32位Windows系统上的64位应用),但在某些情况下,它可能因安装或配置而异。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
  
int main() {  
    TCHAR systemDir[MAX_PATH]; // MAX_PATH 是预定义的最大路径长度  
    UINT result = GetSystemDirectory(systemDir, MAX_PATH);  
      
    if (result != 0 && result < MAX_PATH) {  
        std::wcout << L"System directory: " << systemDir << std::endl;  
    } else {  
        std::cerr << "Error occurred or buffer was too small." << std::endl;  
        if (result == 0) {  
            // 获取具体的错误代码  
            DWORD errorCode = GetLastError();  
            std::cerr << "Error code: " << errorCode << std::endl;  
        }  
    }  
  
    return 0;  
}


注意:上述代码使用宽字符(Unicode)版本的GetSystemDirectory函数(隐式地通过TCHAR和MAX_PATH)。如果你正在使用ANSI版本的API,请确保你的项目设置和代码与之兼容。

(7)使用时的注意事项

  1. 缓冲区大小:确保lpBuffer缓冲区足够大,以容纳系统目录路径的完整内容,包括null终止字符。如果缓冲区太小,函数将失败,并设置GetLastError为ERROR_INSUFFICIENT_BUFFER。
  2. 错误处理:检查返回值以确定是否成功获取了系统目录路径。如果返回值为0,使用GetLastError获取更详细的错误信息。
  3. 权限:通常,任何进程都可以调用此函数来获取系统目录路径,但访问该目录中的文件或子目录可能需要特定的权限。
  4. 线程安全:在多线程环境中,如果多个线程同时调用此函数并访问相同的缓冲区,可能会导致数据竞争或其他同步问题。确保适当的同步机制。
  5. 兼容性:虽然这个函数在大多数Windows版本上都是可用的,但最好检查你的目标平台是否支持它。

3.42 函数名:GetTempFileName


(1)函数的概述
GetTempFileName 是一个Windows API函数,用于在指定的目录下创建一个具有唯一文件名的临时文件。这个函数不仅返回文件名的字符串,而且如果指定了CREATE_NEW标志,它还会在文件系统中实际创建该文件。

(2)函数所在的动态链接库
GetTempFileName 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

UINT GetTempFileName(  
  LPCTSTR lpPathName,  
  LPCTSTR lpPrefixString,  
  UINT    uUnique,  
  LPTSTR  lpTempFileName  
);


(4)各参数及返回值的详细解释

  • lpPathName:一个指向字符串的指针,指定了要创建临时文件的目录。如果这个参数是NULL或指向一个空字符串,函数会在系统的临时文件目录下创建文件。
  • lpPrefixString:一个指向字符串的指针,指定了临时文件名的前缀。文件名将基于这个前缀和一个唯一的数字后缀生成。
  • uUnique:一个唯一值,通常设置为0,让系统生成一个唯一的数字后缀。如果应用程序指定了一个非零值,这个数字将被用作后缀的起始值,并且如果此值已存在,系统将递增它直到找到一个唯一的文件名。
  • lpTempFileName:一个指向字符串缓冲区的指针,用于接收生成的临时文件名的完整路径。这个缓冲区的大小应该足够大,以容纳MAX_PATH个字符。
  • 返回值:如果函数成功,返回值是生成的文件名的长度(不包括终止的null字符)。如果函数失败,返回值是0,可以通过调用GetLastError函数获取更多错误信息。

(5)函数的详细作用
GetTempFileName函数的主要作用是创建一个具有唯一文件名的临时文件。它确保了即使在同一目录下同时有多个应用程序或进程运行,也不会因为文件名冲突而导致问题。此外,如果指定了CREATE_NEW标志(尽管这个标志不是GetTempFileName的直接参数,但可以在调用CreateFile时使用返回的文件名时指定),则该函数还会在文件系统中实际创建该文件。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
  
int main() {  
    TCHAR tempPath[MAX_PATH];  
    if (GetTempPath(MAX_PATH, tempPath) == 0) {  
        std::cerr << "GetTempPath failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    TCHAR tempFileName[MAX_PATH];  
    UINT result = GetTempFileName(tempPath, _T("MYAPP"), 0, tempFileName);  
    if (result == 0) {  
        std::cerr << "GetTempFileName failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    std::wcout << L"Temporary file created: " << tempFileName << std::endl;  
  
    // 如果需要,可以在这里使用tempFileName来打开或创建文件  
  
    return 0;  
}


(7)使用时的注意事项

  1. 确保lpTempFileName指向的缓冲区足够大,以容纳完整的文件路径。
  2. 调用GetTempFileName后,如果不需要立即创建文件,应该谨慎处理返回的文件名,以免它被其他进程或应用程序使用。
  3. 如果在调用GetTempFileName后确实需要创建文件,可以使用CreateFile函数,并指定CREATE_NEW标志以确保文件是新的。
  4. 使用完临时文件后,应该始终删除它以释放磁盘空间。可以使用DeleteFile函数来删除文件。
  5. 如果你的应用程序是多线程的,需要确保对GetTempFileName的调用是线程安全的,或者使用某种同步机制来避免文件名冲突。

3.43 函数名:GetTempPath


(1)函数的概述
GetTempPath 函数是一个Windows API函数,用于检索当前用户临时文件目录的路径。这个目录通常用于存储应用程序在运行时创建的临时文件。

(2)函数所在的动态链接库
GetTempPath 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

DWORD GetTempPath(  
  DWORD   nBufferLength,  
  LPTSTR  lpBuffer  
);


(4)各参数及返回值的详细解释

  • nBufferLength:指定lpBuffer缓冲区的大小(以TCHAR为单位)。如果此值小于所需的缓冲区大小(包括终止的null字符),则缓冲区将不会被填充,函数将返回所需的缓冲区大小(不包括终止的null字符)。
  • lpBuffer:指向接收临时文件目录路径的缓冲区的指针。如果此参数为NULL,则函数将返回所需的缓冲区大小(不包括终止的null字符)。
  • 返回值:
  • 如果函数成功,返回值是复制到lpBuffer的字符数(不包括终止的null字符)。
  • 如果lpBuffer太小,无法容纳完整的路径和终止的null字符,则返回值是所需的缓冲区大小(不包括终止的null字符)。
  • 如果函数失败,返回值是0。要获取扩展的错误信息,可以调用GetLastError。

(5)函数的详细作用
GetTempPath 函数的主要作用是检索当前用户的临时文件目录路径。这个目录通常用于存储不需要永久保留的文件,如缓存文件、备份文件等。由于不同的用户可能有不同的临时文件目录(例如,出于安全或配置的原因),因此使用GetTempPath可以确保应用程序将临时文件存储在正确的位置。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
  
int main() {  
    TCHAR tempPath[MAX_PATH];  
    DWORD result = GetTempPath(MAX_PATH, tempPath);  
    if (result == 0 || result > MAX_PATH) {  
        std::cerr << "GetTempPath failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    std::wcout << L"Temporary path is: " << tempPath << std::endl;  
  
    // 可以在这里使用tempPath来创建临时文件或目录  
  
    return 0;  
}


(7)使用时的注意事项

  1. 缓冲区大小:确保为lpBuffer分配了足够的空间来存储完整的路径和终止的null字符。通常,使用MAX_PATH作为缓冲区大小是安全的。
  2. 错误处理:检查GetTempPath的返回值以确保成功,并使用GetLastError获取任何错误信息。
  3. 临时文件管理:在使用GetTempPath返回的临时目录创建文件后,请确保在不再需要这些文件时删除它们,以避免占用磁盘空间。
  4. 线程安全:在多线程环境中,如果多个线程同时调用GetTempPath,并且它们共享相同的缓冲区,则需要适当的同步机制来避免数据竞争。
  5. 权限问题:虽然GetTempPath返回的目录通常对所有用户都是可写的,但在某些情况下(如受限的用户帐户或特定的安全策略),可能没有足够的权限来创建或写入文件。在这种情况下,应用程序应该适当地处理错误。

3.44 函数名:GetVolumeInformation


(1)函数的概述
GetVolumeInformation 是一个Windows API函数,用于获取有关卷的信息,如卷的名称、序列号、文件系统类型、是否支持压缩等。这些信息通常用于文件管理和系统监控等任务。

(2)函数所在的动态链接库
GetVolumeInformation 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

BOOL GetVolumeInformation(  
  LPCTSTR lpRootPathName,  
  LPTSTR  lpVolumeNameBuffer,  
  DWORD   nVolumeNameSize,  
  LPDWORD lpVolumeSerialNumber,  
  LPDWORD lpMaximumComponentLength,  
  LPDWORD lpFileSystemFlags,  
  LPTSTR  lpFileSystemNameBuffer,  
  DWORD   nFileSystemNameSize  
);


(4)各参数及返回值的详细解释

  • lpRootPathName:指向一个字符串的指针,该字符串指定了要获取信息的卷的根目录的路径。例如,可以是"C:"或"\?\Volume{GUID}"。
  • lpVolumeNameBuffer:指向一个缓冲区,用于接收卷的显示名称。这个名称通常是由用户或管理员指定的卷标签。
  • nVolumeNameSize:指定lpVolumeNameBuffer缓冲区的大小(以TCHAR为单位)。
  • lpVolumeSerialNumber:指向一个DWORD变量的指针,该变量接收卷的序列号。
  • lpMaximumComponentLength:指向一个DWORD变量的指针,该变量接收文件系统支持的最大文件名组件长度(例如,目录名或文件名中的一部分,不包括路径分隔符)。
  • lpFileSystemFlags:指向一个DWORD变量的指针,该变量接收一个或多个标志,表示卷的文件系统特性。
  • lpFileSystemNameBuffer:指向一个缓冲区,用于接收文件系统的名称(如"FAT32"、"NTFS"等)。
  • nFileSystemNameSize:指定lpFileSystemNameBuffer缓冲区的大小(以TCHAR为单位)。
  • 返回值:如果函数成功,返回值为非零。如果函数失败,返回值为零,可以调用GetLastError函数获取更多错误信息。

(5)函数的详细作用
GetVolumeInformation 函数用于获取指定卷的详细信息,包括卷的名称、序列号、最大文件名组件长度、文件系统类型以及支持的文件系统特性(如是否支持压缩、磁盘配额等)。这些信息对于应用程序来说可能是有用的,例如,在创建或管理文件时,了解文件系统的限制和特性可以帮助避免错误和提高效率。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
#include <string>  
  
int main() {  
    TCHAR volumeName[MAX_PATH];  
    DWORD volumeSerialNumber;  
    DWORD maxComponentLength;  
    DWORD fileSystemFlags;  
    TCHAR fileSystemName[MAX_PATH];  
  
    if (GetVolumeInformation(TEXT("C:\\"), volumeName, MAX_PATH, &volumeSerialNumber,  
                             &maxComponentLength, &fileSystemFlags, fileSystemName, MAX_PATH)) {  
        std::wcout << L"Volume Name: " << volumeName << std::endl;  
        std::wcout << L"Volume Serial Number: " << volumeSerialNumber << std::endl;  
        std::wcout << L"Max Component Length: " << maxComponentLength << std::endl;  
        std::wcout << L"File System Flags: " << fileSystemFlags << std::endl;  
        std::wcout << L"File System Name: " << fileSystemName << std::endl;  
    } else {  
        std::cerr << "GetVolumeInformation failed: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}


(7)使用时的注意事项

  1. 缓冲区大小:确保为lpVolumeNameBuffer和lpFileSystemNameBuffer分配了足够的空间来存储可能的最大名称长度。通常使用MAX_PATH作为缓冲区大小是安全的。
  2. 空指针检查:如果某些参数不是必需的,可以传递NULL作为它们的值,但相应的n...Size参数应设置为0。
  3. 错误处理:检查GetVolumeInformation的返回值,并在失败时调用GetLastError以获取更详细的错误信息。
  4. 权限问题:在某些情况下,访问某些卷的信息可能需要特定的权限。如果应用程序在没有足够权限的情况下运行,GetVolumeInformation可能会失败。
  5. 路径格式:确保lpRootPathName指定的路径格式正确,特别是当使用长文件路径(例如\\?\Volume{GUID}\)时。

3.45 函数名:GetWindowsDirectory


(1)函数的概述
GetWindowsDirectory 函数用于检索Windows操作系统的安装目录(通常是 C:\Windows,但也可以是其他路径,如 D:\Windows 等,取决于安装时的选择)。

(2)函数所在的动态链接库
GetWindowsDirectory 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

UINT GetWindowsDirectory(  
  LPTSTR lpBuffer,  
  UINT   uSize  
);


(4)各参数及返回值的详细解释

  • lpBuffer:指向一个缓冲区的指针,该缓冲区用于接收Windows目录的路径。
  • uSize:指定lpBuffer缓冲区的大小(以字符为单位)。
  • 返回值:
  • 如果函数成功,返回值是复制到lpBuffer的字符数(不包括终止的空字符)。
  • 如果lpBuffer太小,无法容纳完整的路径和终止的空字符,返回值是所需的缓冲区大小(不包括终止的空字符)。
  • 如果函数失败,返回值是0。要获取扩展的错误信息,可以调用GetLastError函数。

(5)函数的详细作用
GetWindowsDirectory 函数的主要作用是检索Windows系统的安装目录,并将该目录的路径复制到提供的缓冲区中。这对于那些需要访问或引用Windows目录下文件或文件夹的应用程序来说是非常有用的。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
#include <string>  
  
int main() {  
    TCHAR windowsDir[MAX_PATH];  
    UINT result = GetWindowsDirectory(windowsDir, MAX_PATH);  
  
    if (result == 0 || result > MAX_PATH) {  
        std::cerr << "GetWindowsDirectory failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    std::wcout << L"Windows Directory: " << windowsDir << std::endl;  
  
    // 可以在这里使用windowsDir变量  
  
    return 0;  
}


(7)使用时的注意事项

  1. 缓冲区大小:确保为lpBuffer分配了足够的空间来存储Windows目录的完整路径。通常使用MAX_PATH常量(定义为260个字符)作为缓冲区大小是足够的。
  2. 错误处理:检查GetWindowsDirectory的返回值以确保操作成功。如果返回值为0,可以使用GetLastError函数来获取更详细的错误信息。
  3. 线程安全:在多线程环境中,如果多个线程同时调用GetWindowsDirectory函数并共享相同的缓冲区,则需要适当的同步机制来避免数据竞争。
  4. 访问权限:在大多数情况下,任何进程都可以调用GetWindowsDirectory函数。但是,在某些受限的环境中(如某些沙盒环境或具有严格安全策略的环境),可能无法访问Windows目录或获取其路径。在这些情况下,GetWindowsDirectory函数可能会失败。

3.46 函数名:MapViewOfFile


(1)函数的概述
MapViewOfFile 函数用于将一个文件映射对象(由CreateFileMapping创建)映射到调用进程的地址空间中,从而使得应用程序能够像访问内存一样直接访问文件内容。这种方式通常用于高效地读取和写入大文件,因为它允许文件被随机访问,而无需每次都进行磁盘I/O操作。

(2)函数所在的动态链接库
MapViewOfFile 函数位于 Kernel32.dll 动态链接库中。

(3)函数的原型

LPVOID MapViewOfFile(  
  HANDLE hFileMappingObject,  
  DWORD  dwDesiredAccess,  
  DWORD  dwFileOffsetHigh,  
  DWORD  dwFileOffsetLow,  
  SIZE_T dwNumberOfBytesToMap  
);


(4)各参数及返回值的详细解释

  • hFileMappingObject:一个指向文件映射对象的句柄。这个句柄通常是通过CreateFileMapping函数获得的。
  • dwDesiredAccess:指定对文件映射对象的访问权限。可以是FILE_MAP_READ(用于读取)、FILE_MAP_WRITE(用于写入)、FILE_MAP_ALL_ACCESS(用于读写)等标志的组合。
  • dwFileOffsetHigh:文件映射对象中映射区域的起始偏移量的高32位。如果文件小于4GB,这个值通常为0。
  • dwFileOffsetLow:文件映射对象中映射区域的起始偏移量的低32位。与dwFileOffsetHigh组合起来表示完整的文件偏移量。
  • dwNumberOfBytesToMap:要映射的字节数。如果为0,则映射到文件映射对象的整个区域。
  • 返回值:
  • 如果函数成功,返回值是指向映射文件区域的指针。
  • 如果函数失败,返回值为NULL。要获取更多错误信息,可以调用GetLastError函数。

(5)函数的详细作用
MapViewOfFile函数的主要作用是将文件映射对象的一部分或全部映射到调用进程的地址空间中,并返回一个指向该映射区域的指针。映射后,应用程序可以直接通过指针访问文件内容,就像访问内存一样。这种方式可以提高大文件的访问效率,因为它允许随机访问文件,并且减少了磁盘I/O操作的次数。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 假设hFileMappingObject已经通过CreateFileMapping创建  
    HANDLE hFileMappingObject = /* ... */;  
  
    // 映射文件映射对象的前4096字节到进程的地址空间  
    const SIZE_T dwNumberOfBytesToMap = 4096;  
    LPVOID pMapView = MapViewOfFile(hFileMappingObject, FILE_MAP_READ, 0, 0, dwNumberOfBytesToMap);  
  
    if (pMapView == NULL) {  
        std::cerr << "MapViewOfFile failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    // 假设现在你可以通过pMapView指针访问文件内容  
    // ...  
  
    // 当你完成对映射区域的访问后,应使用UnmapViewOfFile函数来解除映射  
    if (!UnmapViewOfFile(pMapView)) {  
        std::cerr << "UnmapViewOfFile failed: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    // 关闭hFileMappingObject句柄(如果不再需要)  
    // CloseHandle(hFileMappingObject);  
  
    return 0;  
}

(7)使用时的注意事项

  1. 在使用MapViewOfFile之前,确保已经通过CreateFileMapping函数成功创建了一个文件映射对象,并获取了有效的句柄。
  2. 调用MapViewOfFile后,需要记住返回的指针,并通过这个指针来访问映射的文件内容。
  3. 当完成对映射区域的访问后,应使用UnmapViewOfFile函数来解除映射,并释放相关的资源。
  4. 如果MapViewOfFile失败,应该调用GetLastError函数来获取错误代码,并根据错误代码进行相应的错误处理。
  5. 在多线程环境中,需要注意对映射区域的同步访问,以避免数据竞争和不一致性。
  6. 映射的文件大小可能受到系统限制和可用内存的限制。如果尝试映射一个过大的文件,可能会导致失败。

3.47 函数名:MoveFile


(1)函数的概述
MoveFile 是一个Windows API函数,用于移动(重命名)文件或目录。如果目标位置在不同的驱动器上,它还会将文件从一个位置移动到另一个位置。

(2)函数所在的动态链接库
MoveFile 函数位于 kernel32.dll 动态链接库中。

(3)函数的原型

BOOL MoveFile(  
  LPCTSTR lpExistingFileName,  
  LPCTSTR lpNewFileName  
);  
  
BOOL MoveFileEx(  
  LPCTSTR lpExistingFileName,  
  LPCTSTR lpNewFileName,  
  DWORD   dwFlags  
);


注意:这里提供了两个版本,MoveFile 和 MoveFileEx。MoveFileEx 是扩展版本,提供了更多的选项。这里我们主要讨论 MoveFile,但 MoveFileEx 提供了 MOVEFILE_REPLACE_EXISTING、MOVEFILE_COPY_ALLOWED 等额外的标志。

(4)各参数及返回值的详细解释

  • 对于 MoveFile:
  • lpExistingFileName:指向源文件名(包括路径)的字符串的指针。
  • lpNewFileName:指向新文件名(包括路径)的字符串的指针。
  • 返回值:
  • 如果函数成功,返回值为非零。
  • 如果函数失败,返回值为零。要获取更多错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
MoveFile 函数的主要作用是将一个文件或目录重命名到新的位置(或只是重命名,如果源和目标在同一个目录中)。它不会复制文件,而是移动文件。如果目标位置已经存在同名文件,MoveFile 会失败(除非使用 MoveFileEx 并指定 MOVEFILE_REPLACE_EXISTING 标志)。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 源文件路径  
    const char* sourceFilePath = "C:\\path\\to\\source\\file.txt";  
    // 目标文件路径  
    const char* destinationFilePath = "C:\\path\\to\\destination\\file.txt";  
  
    // 调用 MoveFile 函数  
    if (MoveFile(sourceFilePath, destinationFilePath)) {  
        std::cout << "File moved successfully." << std::endl;  
    } else {  
        std::cerr << "Failed to move file: " << GetLastError() << std::endl;  
    }  
  
    return 0;  
}


(7)使用时的注意事项

  1. 权限:确保调用进程具有对源文件和目标位置的适当访问权限。
  2. 目标存在:如果目标位置已经存在同名文件,并且没有使用 MoveFileEx 及其 MOVEFILE_REPLACE_EXISTING 标志,则 MoveFile 将失败。
  3. 路径长度:确保文件路径不超过 MAX_PATH(通常为260个字符,但可以通过某些技术扩展)。
  4. 跨驱动器移动:如果源文件和目标位置位于不同的驱动器上,MoveFile 会移动文件而不是重命名它。这可能会比在同一驱动器上重命名文件慢得多。
  5. 错误处理:检查 MoveFile 的返回值,并在失败时调用 GetLastError 以获取更多信息。
  6. 链接库:确保你的程序链接了 kernel32.dll。这通常是自动的,但如果你在使用特定的构建系统或工具,可能需要手动指定。
  7. 线程安全:MoveFile 是线程安全的,但如果在多线程环境中使用,请确保对文件路径的访问是同步的,以避免竞态条件。

3.48 函数名:OpenFileMapping


(1)函数的概述
OpenFileMapping 函数是Windows API的一部分,它用于打开一个已存在的命名文件映射对象。命名文件映射对象允许进程间共享内存。文件映射对象包含文件或内存对象的视图,这些对象可以被映射到进程的地址空间中。

(2)函数所在的动态链接库
OpenFileMapping 函数位于 kernel32.dll 动态链接库中。

(3)函数的原型

HANDLE OpenFileMapping(  
  DWORD   dwDesiredAccess,  
  BOOL    bInheritHandle,  
  LPCWSTR lpName  
);


(4)各参数及返回值的详细解释

  • dwDesiredAccess:指定对文件映射对象的访问权限。这通常是FILE_MAP_READ、FILE_MAP_WRITE或两者兼有。
  • bInheritHandle:指定返回的句柄是否可由子进程继承。如果此参数为TRUE,则句柄可由子进程继承;如果为FALSE,则句柄不能由子进程继承。
  • lpName:指向命名文件映射对象的名称的指针。此名称是调用CreateFileMapping函数时指定的名称。
  • 返回值:
  • 如果函数成功,返回值是文件映射对象的句柄。
  • 如果函数失败,返回值是NULL。要获取更多错误信息,可以调用GetLastError函数。

(5)函数的详细作用
OpenFileMapping函数的主要作用是打开一个已存在的命名文件映射对象,以便在调用进程中访问该文件映射对象。一旦文件映射对象被打开,可以使用MapViewOfFile函数将其映射到进程的地址空间中,从而允许进程读取、写入或修改文件映射对象中的数据。

(6)函数的C++示

#include <windows.h>  
#include <iostream>  
  
int main() {  
    // 假设存在一个名为"MyFileMapping"的文件映射对象  
    const wchar_t* mappingName = L"MyFileMapping";  
  
    // 打开文件映射对象  
    HANDLE hFileMap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mappingName);  
    if (hFileMap == NULL) {  
        std::wcerr << L"Error opening file mapping: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    // 接下来,可以使用MapViewOfFile函数将文件映射对象映射到地址空间中  
    // ...  
  
    // 关闭文件映射对象句柄  
    CloseHandle(hFileMap);  
  
    return 0;  
}


(7)使用时的注意事项

  1. 确保你有足够的权限来访问指定的文件映射对象。
  2. 在处理完文件映射对象后,记得使用CloseHandle函数关闭句柄。
  3. 如果文件映射对象不存在,OpenFileMapping函数将失败,并返回NULL。在调用OpenFileMapping之前,你可能需要确认文件映射对象是否已存在。
  4. 如果多个进程同时访问同一个文件映射对象,请确保使用适当的同步机制(如互斥量、信号量等)来避免数据冲突。
  5. 当映射文件到地址空间时,请注意内存对齐和内存大小的问题,以确保正确地访问和修改数据。

3.49 函数名:QueryDosDevice


(1)函数的概述
QueryDosDevice 是一个Windows API函数,用于查询MS-DOS设备名的映射。在Windows中,某些设备名(如 CON, PRN, COM1, LPT1 等)被保留用于与MS-DOS兼容。这些设备名通常映射到Windows设备名(如 \Device\Console, \Device\Lpt1 等)。QueryDosDevice 函数允许你查询这些映射。

(2)函数所在的动态链接库
QueryDosDevice 函数位于 kernel32.dll 动态链接库中。

(3)函数的原型

DWORD QueryDosDevice(  
  LPCTSTR lpDeviceName,  
  LPTSTR  lpTargetPath,  
  DWORD   ucchMax;  
);


(4)各参数及返回值的详细解释

  • lpDeviceName:指向要查询的MS-DOS设备名的字符串的指针。
  • lpTargetPath:指向接收Windows设备名映射的缓冲区的指针。
  • ucchMax:lpTargetPath 缓冲区的大小(以TCHAR为单位)。
  • 返回值:
  • 如果函数成功,返回值是复制到 lpTargetPath 的字符数(不包括终止的空字符)。
  • 如果函数失败,返回值是0。要获取更多错误信息,可以调用 GetLastError 函数。

(5)函数的详细作用
QueryDosDevice 函数的作用是获取指定MS-DOS设备名对应的Windows设备名。这在需要知道MS-DOS设备名在Windows内部如何表示时非常有用,例如,在编写与MS-DOS设备交互的底层代码时。

(6)函数的C++示例

#include <windows.h>  
#include <iostream>  
  
int main() {  
    TCHAR deviceName[] = TEXT("CON");  
    TCHAR targetPath[MAX_PATH];  
  
    DWORD result = QueryDosDevice(deviceName, targetPath, MAX_PATH);  
    if (result == 0) {  
        std::cerr << "Error querying DOS device: " << GetLastError() << std::endl;  
        return 1;  
    }  
  
    // 注意:QueryDosDevice不包括结束的空字符,所以需要手动添加  
    targetPath[result] = TEXT('\0');  
  
    std::wcout << TEXT("DOS Device: ") << deviceName << TEXT("\n");  
    std::wcout << TEXT("Windows Device: ") << targetPath << std::endl;  
  
    return 0;  
}


(7)使用时的注意事项

  1. 确保 lpTargetPath 缓冲区足够大,以容纳返回的Windows设备名加上终止的空字符。通常,使用 MAX_PATH 宏定义的缓冲区大小是安全的。
  2. 注意,返回的Windows设备名不包括结束的空字符,因此在将其视为C风格的字符串之前,你可能需要手动添加它。
  3. 如果函数失败,检查 GetLastError 返回的错误代码以确定失败的原因。
  4. 尽管MS-DOS设备名在Windows中仍然受支持,但在新的Windows应用程序中通常不推荐使用它们,因为它们不是Windows特有的,并且可能在未来版本的Windows中不再受支持。

3.50 函数名:ReadFile


(1)函数的概述
ReadFile 是一个Windows API函数,用于从文件或输入/输出(I/O)设备中读取数据。它通常用于读取文件的内容,但也可以用于读取套接字、管道、命名管道、控制台、通信端口等。

(2)函数所在的动态链接库
ReadFile 函数位于 kernel32.dll 动态链接库中。

(3)函数的原型

BOOL ReadFile(  
  HANDLE       hFile,  
  LPVOID       lpBuffer,  
  DWORD        nNumberOfBytesToRead,  
  LPDWORD      lpNumberOfBytesRead,  
  LPOVERLAPPED lpOverlapped  
);


(4)各参数及返回值的详细解释

  • hFile:文件的句柄或设备的句柄。这是通过CreateFile、CreateNamedPipe等函数获得的。
  • lpBuffer:指向接收数据的缓冲区的指针。
  • nNumberOfBytesToRead:要读取的字节数。
  • lpNumberOfBytesRead:指向一个DWORD变量的指针,该变量接收实际读取的字节数。如果为NULL,则不返回此信息。
  • lpOverlapped:指向一个OVERLAPPED结构的指针,该结构用于异步读取操作。对于同步读取,此参数应为NULL。
  • 返回值:
  • 如果函数成功,返回值为非零值(TRUE)。
  • 如果函数失败,返回值为0(FALSE)。要获取更多错误信息,可以调用GetLastError函数。

(5)函数的详细作用
ReadFile 函数用于从指定的文件或设备中读取数据。它可以用于同步读取(等待操作完成)或异步读取(不等待操作完成,而是立即返回)。在同步读取中,函数会阻塞调用线程,直到读取操作完成或发生错误。在异步读取中,函数会立即返回,而读取操作会在后台进行。

(6)函数的C++示例


#include <windows.h>  
#include <iostream>  
  
int main() {  
    HANDLE hFile = CreateFile(  
        TEXT("example.txt"),           // 文件名  
        GENERIC_READ,                  // 访问权限  
        FILE_SHARE_READ,               // 共享模式  
        NULL,                          // 安全描述符  
        OPEN_EXISTING,                 // 如何创建  
        FILE_ATTRIBUTE_NORMAL,          // 文件属性  
        NULL                           // 模板文件句柄  
    );  
  
    if (hFile == INVALID_HANDLE_VALUE) {  
        std::cerr << "Error opening file." << std::endl;  
        return 1;  
    }  
  
    char buffer[1024];  
    DWORD bytesRead;  
    BOOL result = ReadFile(  
        hFile,                         // 文件句柄  
        buffer,                        // 接收数据的缓冲区  
        sizeof(buffer) - 1,             // 要读取的字节数  
        &bytesRead,                    // 接收实际读取字节数的变量  
        NULL                           // 不使用异步操作  
    );  
  
    if (!result) {  
        std::cerr << "Error reading file." << std::endl;  
        CloseHandle(hFile);  
        return 1;  
    }  
  
    buffer[bytesRead] = '\0'; // 确保字符串以null终止  
    std::cout << "Read " << bytesRead << " bytes: " << buffer << std::endl;  
  
    CloseHandle(hFile);  
    return 0;  
}

(7)使用时的注意事项

  1. 确保在调用ReadFile之前已经打开了文件或设备,并且获得了有效的句柄。
  2. 读取的缓冲区应足够大,以容纳请求的数据量。如果缓冲区太小,则可能只读取部分数据。
  3. 如果ReadFile用于异步读取,请确保正确处理OVERLAPPED结构,并准备好处理可能的异步完成通知。
  4. 在读取完成后,请检查实际读取的字节数是否与预期的字节数匹配,因为某些情况下(如文件结束或读取错误)可能会读取到较少的字节。
  5. 使用完句柄后,请通过调用CloseHandle函数关闭它,以避免资源泄漏。
  6. 在多线程环境中使用ReadFile时,请确保对文件句柄的访问是同步的,以避免竞态条件。

其它API链接:

windows API函数集

windows API函数之文件类函数(一)

windows API函数之文件类函数(三)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hn_tzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值