一、SHCreateDirectoryEx 函数(支持安全属性)
SHCreateDirectoryEx
函数是 Windows API 中用于创建目录的函数。它允许开发者创建一个指定路径的目录,如果该目录已经存在,则不会进行任何操作。
函数原型
HRESULT SHCreateDirectoryEx(
HWND hwnd,
PCWSTR pszPath,
LPSECURITY_ATTRIBUTES psa
);
参数说明
-
hwnd:
- 类型:
HWND
- 描述:一个窗口句柄,通常用于显示任何可能的错误消息。如果不需要显示错误消息,可以传递
NULL
。
- 类型:
-
pszPath:
- 类型:
PCWSTR
- 描述:指向要创建的目录的路径的指针。该路径可以是相对路径或绝对路径。
- 类型:
-
psa:
- 类型:
LPSECURITY_ATTRIBUTES
- 描述:指向
SECURITY_ATTRIBUTES
结构的指针,该结构定义了新目录的安全描述符。如果不需要自定义安全性,可以传递NULL
。
- 类型:
返回值
- 如果函数成功,返回
S_OK
。 - 如果函数失败,返回相应的 HRESULT 错误代码。
使用示例
以下是一个简单的示例,展示如何使用 SHCreateDirectoryEx
逐级创建目录:
#include <windows.h>
#include <shlobj.h>
#include <iostream>
int main()
{
// 要创建的目录路径
PCWSTR path = L"C:\\Example\\1\\2\\3";
// 调用 SHCreateDirectoryEx
HRESULT result = SHCreateDirectoryEx(NULL, path, NULL);
if (SUCCEEDED(result))
{
std::wcout << L"目录创建成功: " << path << std::endl;
}
else
{
std::wcerr << L"目录创建失败,错误代码: " << result << std::endl;
}
return 0;
}
注意事项
- 错误处理: 在使用时务必检查返回值,以确保目录创建成功。
- Unicode 支持:
SHCreateDirectoryEx
是支持 Unicode 的,因此建议使用宽字符字符串(如示例中所示)。 - 权限问题: 创建目录可能会受到用户权限的限制。确保程序有足够的权限以创建指定位置的目录。
- 包含头文件和库: 使用该函数时,需要包含
<windows.h>
和<shlobj.h>
头文件,并在编译时链接到Shell32.lib
。
二、SHCreateDirectory 函数(不支持安全属性)
SHCreateDirectory
函数是 Windows API 用于创建一个新目录的函数。与 SHCreateDirectoryEx
相似,但 SHCreateDirectory
不支持安全属性参数,适合用于简单的目录创建任务。
函数原型
HRESULT SHCreateDirectory(
HWND hwnd,
PCWSTR pszPath
);
参数说明
-
hwnd:
- 类型:
HWND
- 描述:一个窗口句柄,用于显示可能的错误消息。如果不需要显示错误消息,可以传递
NULL
。
- 类型:
-
pszPath:
- 类型:
PCWSTR
- 描述:指向要创建的目录路径的指针。该路径可以是相对路径或绝对路径。
- 类型:
返回值
- 如果函数成功,返回
S_OK
。 - 如果函数失败,返回相应的 HRESULT 错误代码,可以使用
HRESULT_FROM_WIN32(GetLastError())
来获取更多的错误信息。
使用示例
以下是一个简单的示例,展示如何使用 SHCreateDirectory
逐级创建目录:
#include <windows.h>
#include <shlobj.h>
#include <iostream>
int main()
{
// 要创建的目录路径
PCWSTR path = L"C:\\Example\\1\\2\\3";
// 调用 SHCreateDirectory
HRESULT result = SHCreateDirectory(NULL, path);
if (SUCCEEDED(result))
{
std::wcout << L"目录创建成功: " << path << std::endl;
}
else
{
std::wcerr << L"目录创建失败,错误代码: " << HRESULT_CODE(result) << std::endl;
}
return 0;
}
注意事项
- 错误处理: 确保检查返回值,以确保目录创建成功,并可以根据返回的 HRESULT 错误代码执行适当的错误处理。
- Unicode 支持:
SHCreateDirectory
是支持 Unicode 的,因此建议使用宽字符字符串(如示例中所示)。 - 权限问题: 创建目录可能会受到用户权限限制,因此确保程序有足够的权限来创建指定位置的目录。
- 包含头文件和库: 使用该函数时,需要包含
<windows.h>
和<shlobj.h>
头文件,并在编译时链接到Shell32.lib
。
三、仿照上述API实现 CreateDirectoryRecursively 函数
#include <windows.h>
#include <iostream>
#include <string>
bool DirectoryExists(const std::string& path)
{
DWORD attributes = GetFileAttributes(path.c_str());
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool CreateDirectoryRecursively(const std::string& path, DWORD attributes = 0)
{
// 检查目录是否已经存在
//if (DirectoryExists(path))
//{
// return true; // 目录已存在
//}
DWORD attr = GetFileAttributes(path.c_str());
bool result = (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY));
if (result)
{
return true; // 目录已存在
}
// 分割路径以获取逐级目录
std::string currentPath;
size_t pos = 0;
while ((pos = path.find_first_of("\\/", pos)) != std::string::npos)
{
currentPath = path.substr(0, pos);
// 创建当前逐级目录
if (!currentPath.empty())
{
if (CreateDirectory(currentPath.c_str(), NULL) ||
GetLastError() == ERROR_ALREADY_EXISTS)
{
// 如果成功或目录已存在,则继续
}
else
{
// 如果创建失败,输出错误信息并返回 false
std::cerr << "创建目录失败: " << currentPath << ", 错误代码: " << GetLastError() << std::endl;
return false;
}
}
pos++; // 移动到下一个分隔符
}
// 最后创建目标目录,并应用属性
if (!CreateDirectory(path.c_str(), NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
{
std::cerr << "创建目录失败: " << path << ", 错误代码: " << GetLastError() << std::endl;
return false;
}
// 应用目录属性(如果需要)
if (attributes != 0)
{
SetFileAttributes(path.c_str(), attributes);
}
return true;
}
int main()
{
std::string path = "C:\\Users\\Admin\\Desktop\\Example\\SubDirectory1\\SubDirectory2";
DWORD attributes = FILE_ATTRIBUTE_NORMAL; // 设定想要的属性
if (CreateDirectoryRecursively(path, attributes))
{
std::cout << "目录创建成功: " << path << std::endl;
}
else
{
std::cerr << "目录创建失败: " << path << std::endl;
}
std::cin.get();
return 0;
}