我正在寻找一种无需打开只读文件即可检查其是否存在的方法。我已尝试:
if (std::filesystem::exists("C:\\Windows\\System32\\hal.dll")) { std::cout << "Exists" << std::endl; } else { std::cout << "Does not exist" << std::endl; }
但它返回“不存在”。我正在寻找一个解决方案,可以检查像这些文件的存在。
lo8azlld1#
std::filesystem::exists()工作正常。但是,您可能没有查询所需的文件。首先,并非每个人都以C:\Windows安装Windows,因此您应该使用GetWindowsDirectory()、SHGetFolderPath(CSIDL_WINDOWS)或SHGetKnownFolderPath(FOLDERID_Windows)询问操作系统的实际安装位置,例如:
std::filesystem::exists()
C:\Windows
GetWindowsDirectory()
SHGetFolderPath(CSIDL_WINDOWS)
SHGetKnownFolderPath(FOLDERID_Windows)
namespace fs = std::filesystem; fs::path getWindowsPath() { WCHAR szPath[MAX_PATH] = {}; GetWindowsDirectoryW(szPath, MAX_PATH); return szPath; // or equivalent... }
其次,在64位Windows系统上,如果在WOW64模拟器中运行的32位应用程序尝试访问64位%WINDIR%\System32文件夹,默认情况下,访问将被重定向到32位%WINDIR%\SysWOW64文件夹,这可以解释为什么您的exists()检查不起作用。要在WOW64下运行时访问64位System32文件夹,您必须执行以下操作之一:
%WINDIR%\System32
%WINDIR%\SysWOW64
exists()
System32
SysNative
bool isWow64() { #ifdef _WIN64 return false; #else BOOL bIsWow64 = FALSE; return IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64; #endif } fs::path getSystemPath() { if (isWow64()) { return getWindowsPath() / "SysNative"; } else { return getWindowsPath() / "System32"; /* alternatively: WCHAR szPath[MAX_PATH] = {}; GetSystemDirectoryW(szPath, MAX_PATH); return szPath; or equivalent... */ } } ... if (std::filesystem::exists(getSystemPath() / "hal.dll")) { std::cout << "Exists" << std::endl; } else { std::cout << "Does not exist" << std::endl; }
Wow64DisableWow64FsRedirection()
fs::path getSystemPath() { return getWindowsPath() / "System32"; // or equivalent ... } ... PVOID oldValue = NULL; if (isWow64()) { Wow64DisableWow64FsRedirection(&oldValue); } if (std::filesystem::exists(getSystemPath() / "hal.dll")) { std::cout << "Exists" << std::endl; } else { std::cout << "Does not exist" << std::endl; } if (isWow64()) { Wow64RevertWow64FsRedirection(oldValue); }
有关详细信息,请参见MSDN上的File System Redirector。
qxgroojn2#
如果在Windows中,函数GetFileAttributes返回文件存在但未打开的属性。出错时,它返回INVALID_FILE_ATTRIBUTES,然后您可以使用GetLastError()进行检查。如果您正在检查以便稍后打开它,则可能导致争用情况(如前所述TOCTOU bug)。除此之外,确实有理由检查文件是否存在而不打算打开它,例如安装程序要查看要替换的文件是否存在并警告用户。
2条答案
按热度按时间lo8azlld1#
std::filesystem::exists()
工作正常。但是,您可能没有查询所需的文件。首先,并非每个人都以
C:\Windows
安装Windows,因此您应该使用GetWindowsDirectory()
、SHGetFolderPath(CSIDL_WINDOWS)
或SHGetKnownFolderPath(FOLDERID_Windows)
询问操作系统的实际安装位置,例如:其次,在64位Windows系统上,如果在WOW64模拟器中运行的32位应用程序尝试访问64位
%WINDIR%\System32
文件夹,默认情况下,访问将被重定向到32位%WINDIR%\SysWOW64
文件夹,这可以解释为什么您的exists()
检查不起作用。要在WOW64下运行时访问64位
System32
文件夹,您必须执行以下操作之一:SysNative
别名,例如:Wow64DisableWow64FsRedirection()
函数暂时禁用重定向,例如:有关详细信息,请参见MSDN上的File System Redirector。
qxgroojn2#
如果在Windows中,函数GetFileAttributes返回文件存在但未打开的属性。出错时,它返回INVALID_FILE_ATTRIBUTES,然后您可以使用GetLastError()进行检查。
如果您正在检查以便稍后打开它,则可能导致争用情况(如前所述TOCTOU bug)。
除此之外,确实有理由检查文件是否存在而不打算打开它,例如安装程序要查看要替换的文件是否存在并警告用户。