Find File Directory By Searching Through Hard Drive

萝らか妹 提交于 2019-12-13 08:56:16

问题


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 a const char[] to a const wchar_t*. To make a proper wide string literal, you need to use L"HxD.exe" instead (or TEXT("HxD.exe") since you are using the TCHAR version of the API).

  • You are passing in a NULL WIN32_FIND_DATA* pointer. FindFirstFile() (and FindNextFile()) expects a pointer to a pre-allocated WIN32_FIND_DATA instance, but you are not allocating anything.

  • You are checking for a FindFirstFile() failure incorrectly. The return value will be INVALID_HANDLE_VALUE if the function fails. You are not checking for that condition.

  • Lastly, you are asking FindFirstFile() to find HxD.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, and FindNextFile() 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!