API FindFirstFile не нашел все файлы в каталоге - PullRequest
0 голосов
/ 13 июня 2018

У меня есть следующий код для поиска файла в моем продукте:

destFolder = "c:\\myproduct\\base\\";

//download and unzip whoisactive.zip from some websites to the installation folder of my product
DownloadAndUnzipSql( "http://www.whoisactive.com/whoisactive.zip", destFolder)

WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(destFolder.c_str(), &ffd);

do {
    if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
        if ((string(ffd.cFileName).find("whoisactive") != string::npos) && (string(ffd.cFileName).find("sql") != string::npos)){
            MoveFile(ffd.cFileName, sqlFile.c_str());
            log.Debug(__FUNCTION__, "Succeed to rename file.");
            break;
        }
    }
} while (FindNextFile(hFind, &ffd) != 0);           

FindClose(hFind);

Раньше он работал очень хорошо, но не может найти скачанный whoisactive.sql за последний месяц внезапно.Я проверил c: \ myproduct \ base \, whoisactive.sql был там, но когда я сбросил все файлы FindFirstFile и FindNextFile, whoisactive.sql не был включен.

Я не думаю,что оно вызвано антивирусным программным обеспечением, поскольку в среде продукта такое программное обеспечение не установлено.И я не думаю, что это проблема с правами доступа, потому что whoisactive.sql загружается и разархивируется правильно.

Я погуглил свою проблему и нашел следующие две статьи: https://social.msdn.microsoft.com/Forums/vstudio/en-US/4659a528-dd51-4749-b751-a491bbdf5fa0/findfirstfile-caching?forum=vcgeneral Имеет ли FindFirstFile / FindNextFileВозвращены результаты кэширования пары API?

Похоже, что FindFirstFile будет кэшировать список файлов каталога, поэтому иногда мы не можем найти новые добавленные файлы.Но я не думаю, что это также является основной причиной, потому что странно, что мой код работал очень хорошо в прошлом году и никогда не выходил из строя, и он не может найти whoisactive.sql в последний месяц внезапно и никогда не работает до сих пор.Если проблема с кешем является основной причиной, то почему я всегда могу воспроизвести проблему сейчас?И странно, что код все еще может работать в моей среде разработки, но он не может работать в среде продукта.

Поэтому я изменил свой код на следующий, тогда он работает как в продукте, так и в среде разработки:

destFolder = "c:\\myproduct\\base\\";

//download whoisactive.zip from some websites to the installation folder of my product
Download( "http://www.whoisactive.com/whoisactive.zip", destFolder);

//Unzip the whoisactive.zip and get the extracted file list.
string fileList;
Unzip(destFolder+"\\whoisactive.zip", fileList);

for (int i=0; i<fileList.size(); ++i) {
    if (fileList[i].find("sql") != string::npos && fileList[i].find("whoisactive") != string::npos) {
        string srcFile = destFolder+"\\"+fileList[i];
        string dstFile = destFolder+"\\"+sqlFile;

        if (DeleteFile(dstFile.c_str()) == 0)
            log.Debug(__FUNCTION__, "Failed to delete file %s, error code is %d.", dstFile.c_str(), GetLastError());

        if (MoveFile(srcFile.c_str(), dstFile.c_str()) == 0)
            log.Debug(__FUNCTION__, "Failed to rename file %s, error code is %d.", srcFile.c_str(), GetLastError());

        break;
    }
}

Вы видите, что изменение заключается в том, что я больше не использую FindFirstFile и FindNextFile в своем коде, я просто извлек имя файла из zip-файла и напрямую обращаюсь к файлу.Не могли бы вы сказать мне, почему FindFirstFile и FindNextFile не могут найти загруженный файл sql в моем предыдущем коде?Спасибо.

1 Ответ

0 голосов
/ 13 июня 2018

Вы не ищете содержимое каталога вообще.Вы передаете только сам каталог как есть ("c:\\myproduct\\base\\") в FindFirstFile(), так что это ВСЕ, что он найдет - атрибуты самого каталога, ничего больше.

Комуправильно перечислите каталог, вам нужно вместо этого выполнить поиск по шаблону.Добавьте * или *.* в конец пути к каталогу, например:

destFolder = "c:\\myproduct\\base\\";

//download and unzip whoisactive.zip from some websites to the installation folder of my product
DownloadAndUnzipSql("http://www.whoisactive.com/whoisactive.zip", destFolder);

WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFileA((destFolder + "*.*").c_str(), &ffd);
if (hFind != INVALID_HANDLE_VALUE) {
    do {
        if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            if (lstrcmpiA(ffd.cFileName, "whoisactive.sql") == 0) {
                if (MoveFileA((destFolder + ffd.cFileName).c_str(), (destFolder + sqlFile).c_str()))
                    log.Debug(__FUNCTION__, "Succeed to rename file.");
                else
                    log.Debug(__FUNCTION__, "Failed to rename file, error code is %d.", GetLastError());
                break;
            }
        }
    }
    while (FindNextFileA(hFind, &ffd));

    if (GetLastError() != ERROR_NO_MORE_FILES) {
        log.Debug(__FUNCTION__, "Failed to find next file, error code is %d.", GetLastError());
    }

    FindClose(hFind);
}
else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
    log.Debug(__FUNCTION__, "No files found.");
}
else {
    log.Debug(__FUNCTION__, "Failed to find first file, error code is %d.", GetLastError());
}

Однако, поскольку вы действительно заинтересованы только в конкретном файле, вам не нужно использовать Find(First|Next)File()совсем.Просто позвоните MoveFile() безоговорочно и дайте сбой, если файл не существует:

destFolder = "c:\\myproduct\\base\\";

//download and unzip whoisactive.zip from some websites to the installation folder of my product
DownloadAndUnzipSql("http://www.whoisactive.com/whoisactive.zip", destFolder);

if (MoveFileA((destFolder + "whoisactive.sql").c_str(), (destFolder + sqlFile).c_str()))
    log.Debug(__FUNCTION__, "Succeed to rename file.");
else
    log.Debug(__FUNCTION__, "Failed to rename file, error code is %d.", GetLastError());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...