GetWindowsDirectory

基本概述

GetWindowsDirectoryWindows提供的系统目录获取函数,属于Windows.h头文件,主要用于定位Windows系统安装目录(存放系统核心文件的目录)。随着系统升级,微软也提供了更通用的GetSystemDirectory(获取 System32 目录)SHGetFolderPath(获取各类系统 / 用户目录),但GetWindowsDirectory仍被广泛兼容使用。

基本语法

1
2
3
4
5
6
7
8
9
10
11
// Unicode(宽字符)版本
UINT GetWindowsDirectoryW(
[out] LPWSTR lpBuffer,// 接收路径的目标缓冲区
[in] UINT uSize // 目标缓冲区的大小(字符数)
);

// ANSI 版本
UINT GetWindowsDirectoryA(
[out] LPSTR lpBuffer,
[in] UINT uSize// 目标缓冲区的大小(字节数)
);

返回值
成功:返回复制到缓冲区的字符数(ANSI是字节数,Unicodewchar_t字符数),不包含终止符\0
失败:返回 0;若缓冲区太小,返回值会大于uSize(提示所需的最小缓冲区大小)。

数据类型
UINT

1
typedef unsigned int        UINT;

通用无符号整数(4 字节)。

简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <Windows.h>
#include <wchar.h>

int main()
{
// 示例1:先获取所需缓冲区大小,再分配空间(最安全)
UINT uRequiredSize = 0;
// 第一步:传入NULL获取所需字符数(Unicode 版本返回 wchar_t 字符数)
uRequiredSize = GetWindowsDirectoryW(NULL, 0);
if (uRequiredSize == 0)
{
wprintf(L"获取缓冲区大小失败,错误码:%d\n", GetLastError());
return 1;
}

// 第二步:分配缓冲区(+1 确保包含终止符,实际uRequiredSize已包含所需字符数)
wchar_t* szWinDir = new wchar_t[uRequiredSize + 1];
if (szWinDir == NULL)
{
wprintf(L"内存分配失败\n");
return 1;
}

// 第三步:获取 Windows 目录
UINT uResult = GetWindowsDirectoryW(szWinDir, uRequiredSize + 1);
if (uResult == 0 || uResult > uRequiredSize + 1)
{
wprintf(L"获取 Windows 目录失败,错误码:%d\n", GetLastError());
delete[] szWinDir;
return 1;
}

// 输出结果
wprintf(L"Windows 系统目录:%s\n", szWinDir);

// 示例2:直接使用固定大小缓冲区(常用 MAX_PATH,Windows 定义的最大路径长度)
wchar_t szWinDir2[MAX_PATH] = { 0 };
uResult = GetWindowsDirectoryW(szWinDir2, MAX_PATH);
if (uResult > 0 && uResult <= MAX_PATH)
{
wprintf(L"\n使用固定缓冲区获取:%s\n", szWinDir2);

// 扩展:拼接 System32 目录路径(Windows\System32)
wchar_t szSystem32Dir[MAX_PATH] = { 0 };
swprintf_s(szSystem32Dir, MAX_PATH, L"%s\\System32", szWinDir2);
wprintf(L"System32 目录:%s\n", szSystem32Dir);
}
else
{
wprintf(L"\n固定缓冲区获取失败,所需大小:%d,当前大小:%d\n", uResult, MAX_PATH);
}

// 释放内存
delete[] szWinDir;
return 0;
}

PathCanonicalize

基本概述

PathCanonicalize属于Shlwapi.h头文件(Shell Lightweight API),专门用于路径规范化:它会解析路径中的./../、重复的\等冗余部分,输出一个无冗余、格式统一的绝对路径,解决路径格式不规范导致的文件操作错误问题。

基本语法

1
2
3
4
5
6
7
8
9
10
11
// Unicode(宽字符)版本
BOOL PathCanonicalizeW(
[out] LPWSTR pszBuf,// 接收规范化路径的目标缓冲区
[in] LPCWSTR pszPath// 待规范化的源路径
);

// ANSI 版本
BOOL PathCanonicalizeA(
[out] LPSTR pszBuf,
[in] LPCSTR pszPath
);

返回值
TRUE:规范化成功,pszBuf中存储标准路径;
FALSE:失败(如路径无效、缓冲区不足、路径过长),可通过GetLastError()获取具体错误码。

简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <Windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <wchar.h>

int main()
{
// 示例1:规范化包含 ../ 的相对路径
wchar_t szBuf1[MAX_PATH] = { 0 };
LPCWSTR szPath1 = L"C:\\Windows\\System32\\..\\notepad.exe"; // 包含上级目录
BOOL bResult = PathCanonicalizeW(szBuf1, szPath1);
if (bResult)
{
wprintf(L"示例1 - 源路径:%s\n", szPath1);
wprintf(L"规范化后:%s\n\n", szBuf1);
}
else
{
wprintf(L"示例1失败,错误码:%d\n", GetLastError());
}

// 示例2:规范化包含 ./ 和重复 \ 的路径
wchar_t szBuf2[MAX_PATH] = { 0 };
LPCWSTR szPath2 = L"C:\\Windows\\\\./Temp\\./test.txt"; // 包含冗余 ./ 和重复 \
bResult = PathCanonicalizeW(szBuf2, szPath2);
if (bResult)
{
wprintf(L"示例2 - 源路径:%s\n", szPath2);
wprintf(L"规范化后:%s\n\n", szBuf2);
}

// 示例3:规范化相对路径(基于当前工作目录)
wchar_t szBuf3[MAX_PATH] = { 0 };
LPCWSTR szPath3 = L"../Documents/test.txt"; // 相对路径
bResult = PathCanonicalizeW(szBuf3, szPath3);
if (bResult)
{
wprintf(L"示例3 - 源路径:%s\n", szPath3);
wprintf(L"规范化后(绝对路径):%s\n\n", szBuf3);
}

// 示例4:无效路径(规范化失败)
wchar_t szBuf4[MAX_PATH] = { 0 };
LPCWSTR szPath4 = L"\\\\\\无效的路径\\..\\test.txt"; // 无效路径
bResult = PathCanonicalizeW(szBuf4, szPath4);
if (!bResult)
{
wprintf(L"示例4 - 源路径:%s\n", szPath4);
wprintf(L"规范化失败,错误码:%d\n", GetLastError());
}

return 0;
}

PathIsRelative

基本概述

PathIsRelative属于Shlwapi.h头文件(Shell Lightweight API),是一个轻量级的路径类型判断函数:它不解析路径内容,仅通过路径的格式特征判断是否为相对路径,返回布尔值,无缓冲区操作,效率极高。

基本语法

1
2
3
4
5
6
7
8
9
// Unicode(宽字符)版本
BOOL PathIsRelativeW(
[in] LPCWSTR pszPath// 待判断的路径字符串
);

// ANSI 版本
BOOL PathIsRelativeA(
[in] LPCSTR pszPath
);

返回值
TRUE:路径是相对路径(如test.txt、../DocumentsSystem32/notepad.exe);
FALSE:路径是绝对路径(如C:\Windows\\server\shareD:\Temp\test.txt)。

简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <Windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <wchar.h>

int main()
{
// 定义待判断的路径数组
LPCWSTR paths[] = {
L"C:\\Windows\\notepad.exe", // 绝对路径(盘符开头)
L"\\\\server\\share\\file.txt",// 绝对路径(UNC)
L"../Documents/test.txt", // 相对路径(../开头)
L"./temp.txt", // 相对路径(./开头)
L"test.txt", // 相对路径(无起始符)
L"\\Temp\\test.txt", // 相对路径(\开头,无盘符)
L"System32\\calc.exe" // 相对路径(子目录)
};
int pathCount = _countof(paths);

// 遍历判断每个路径
for (int i = 0; i < pathCount; i++)
{
BOOL isRelative = PathIsRelativeW(paths[i]);
wprintf(L"路径:%s\n", paths[i]);
wprintf(L"是否相对路径:%s\n\n", isRelative ? L"是" : L"否");
}

return 0;
}