问题
So I am trying to search through a specific hard drive (for example, C:) to find a file (like "HxD.exe"), and I am trying to get the specific directory to that file to launch with CreateProcess()
. I know that this question has been answered before, but I have tried all those methods and none of them have worked for me (well, one worked but the type of string it gave me couldn't be converted to what CreateProcess()
was looking for without losing data). Perhaps I am just doing it wrong? Anyways, if anyone knows anything that would work, if you would please tell me that would be great. I only need it to work for windows.
Code for FindFirstFile()
LPWIN32_FIND_DATA fd = 0;
HANDLE findFile = 0;
do
{
findFile = FindFirstFile((LPCWSTR)"HxD.exe", fd);
if (fd == 0)
{
std::cout << "ERROR " << GetLastError();
// prints "ERROR 2"
}
} while (FindNextFile(findFile, fd));
CloseHandle(findFile);
PS: Sorry if this is a very easy fix, I quickly whipped up some code at midnight because I deleted it all, and I don't have time to look it up b/c I am about to pass out lol.
回答1:
If you are using a C++
compiler that support C++17
version, you can make use of the filesystem
functions. And if you don't have access to C++17 version may be you can try Boost
library.
You can try the recursive_directory_iterator
function to iterate the subdirectories and files recursively and check if file that you are looking for exists.
for(auto& p: fs::recursive_directory_iterator("C:/"))
std::cout << p.path() << '\n'
Rerferences:
std::filesystem
boost filesystem
回答2:
You are using FindFirstFile()
all wrong.
(LPCWSTR)"HxD.exe"
is an invalid type cast. You are casting aconst char[]
to aconst wchar_t*
. To make a proper wide string literal, you need to useL"HxD.exe"
instead (orTEXT("HxD.exe")
since you are using theTCHAR
version of the API).You are passing in a NULL
WIN32_FIND_DATA*
pointer.FindFirstFile()
(andFindNextFile()
) expects a pointer to a pre-allocatedWIN32_FIND_DATA
instance, but you are not allocating anything.You are checking for a
FindFirstFile()
failure incorrectly. The return value will beINVALID_HANDLE_VALUE
if the function fails. You are not checking for that condition.Lastly, you are asking
FindFirstFile()
to findHxD.exe
only in the calling thread's current working directory. And you are not stopping your loop if the file is actually found. In fact, when searching for a specific filename,FindFirstFile()
will either find it or not, andFindNextFile()
will always return FALSE afterwards since there can only be 1 file in a given folder with the name being searched for. So your loop becomes useless.
To search a whole partition correctly, you need to ask the API to search for the *
wildcard instead, and then call the API in a recursive loop for each subdirectory that is found, checking the returned WIN32_FIND_DATA
for non-subdirectories for the filename you are interested in.
With that said, try something more like this:
#include <Shlwapi.h>
bool findFile(LPCWSTR path, LPCWSTR fileName, LPWSTR fullPath)
{
WIN32_FIND_DATAW fd = {};
DWORD dwError;
WCHAR str[MAX_PATH] = {};
PathCombineW(str, path, L"*");
HANDLE hFind = FindFirstFileW(str, &fd);
if (hFind == INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
if (dwError != ERROR_FILE_NOT_FOUND)
std::cout << "ERROR " << dwError;
return false;
}
do
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((lstrcmpW(fd.cFileName, L".") != 0) &&
(lstrcmpW(fd.cFileName, L"..") != 0))
{
PathCombineW(str, path, fd.cFileName);
if (findFile(str, fileName, fullPath))
{
CloseHandle(hFind);
return true;
}
}
}
else
{
if ((lstrcmpiW(fd.cFileName, fileName) == 0) ||
(lstrcmpiW(fd.cAlternateFileName, fileName) == 0))
{
if (fullPath)
PathCombineW(fullPath, path, fd.cFileName);
CloseHandle(hFind);
return true;
}
}
}
while (FindNextFileW(hFind, &fd));
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
std::cout << "ERROR " << dwError;
CloseHandle(hFind);
return false;
}
WCHAR fullPath[MAX_PATH] = {};
if (findFile(L"C:\\", L"HxD.exe", fullPath))
{
// use fullPath as needed...
}
To search an entire hard drive with multiple partitions, you can use GetLogicalDriveStrings():
WCHAR drives[256] = {};
if (GetLogicalDriveStringsW(256, drives))
{
WCHAR fullPath[MAX_PATH] = {};
LPWSTR drive = drives;
while (*drive)
{
if (findFile(drive, L"HxD.exe", fullPath))
{
// use fullPath as needed...
break;
}
drive += (lstrlenW(drive)+1);
}
}
来源:https://stackoverflow.com/questions/59188524/find-file-directory-by-searching-through-hard-drive