CHtmlView::Navigate2 и заблокированные файлы

#mfc #webbrowser-control #navigatetourl

#mfc #веб-браузер-управление #navigatetourl

Вопрос:

Я обнаружил, что если я перейду к файлу, а затем попытаюсь удалить файл, система сообщит мне, что он используется.

Как я могу остановить «использование» файлов, чтобы я мог удалить их и воссоздать заново для обновления отображения html?

Если я каждый раз создаю НОВЫЙ файл данных XML и перехожу к нему, у меня не возникает проблем. Это потому, что нет файла для удаления.

Но в тот момент, когда я использую тот же файл, я получаю проблему с использованием файла.

Я добавил код в свой метод dialog OnDestroy и добавил массив временных файлов, которые я создаю. Затем я пытаюсь их удалить:

 for (auto i = 0; i < m_aryStrTempFiles.GetCount(); i  )
{
    if (PathFileExists(m_aryStrTempFiles[i]))
    {
        if (!::DeleteFile(m_aryStrTempFiles[i]))
        {
            AfxMessageBox(theApp.GetLastErrorAsString(), MB_OK | MB_ICONERROR);
        }
    }
}
  

Я обнаружил, что ВСЕ файлы считаются все еще используемыми.

Проблема не в коде, который создает временные имена файлов:

 CString CMeetingScheduleAssistantApp::GetFolderTempFilenameEx(CString strFolder, CString strToken, CString strSuffix /*_T("htm")*/)
{
    CString     strFile;
    int         i;

    ::GetTempFileName(strFolder, strToken, 0, strFile.GetBuffer(_MAX_PATH));
    strFile.ReleaseBuffer();

    // Because we will rename to .HTM we must delete old file
    ::DeleteFile(strFile);

    // I can't be sure the suffix is .tmp so I manually
    // replace the suffix, whatever it is, with .htm"
    i = strFile.ReverseFind(_T('.'));
    strFile = strFile.Left(i   1);
    strFile  = strSuffix;

    return strFile;
}
  

И это код, который сохраняет мои XML-файлы:

 bool CMeetingScheduleAssistantApp::SaveToXML(CString strFileXML, tinyxml2::XMLDocumentamp; rDocXML)
{
    FILE    *fStream = nullptr;
    CString strError, strErrorCode;
    errno_t eResu<
    bool    bDisplayError = false;
    int     iErrorNo = -1;

    using namespace tinyxml2;

    // Does the file already exist?
    if (PathFileExists(strFileXML))
    {
        // It does, so try to delete it
        if (!::DeleteFile(strFileXML))
        {
            // Unable to delete!
            AfxMessageBox(theApp.GetLastErrorAsString(), MB_OK | MB_ICONINFORMATION);
            return false;
        }
    }

    // Now try to create a FILE buffer (allows UNICODE filenames)
    eResult = _tfopen_s(amp;fStream, strFileXML, _T("w"));
    if (eResult != 0 || fStream == nullptr) // Error
    {
        bDisplayError = true;
        _tcserror_s(strErrorCode.GetBufferSetLength(_MAX_PATH), _MAX_PATH, errno);
        strErrorCode.ReleaseBuffer();
    }
    else // Success
    {
        // Now try to save the XML file
        XMLError eXML = rDocXML.SaveFile(fStream);
        int fileCloseResult = fclose(fStream);
        if (eXML != XMLError::XML_SUCCESS)
        {
            // Error saving
            bDisplayError = true;
            strErrorCode = rDocXML.ErrorName();
            iErrorNo = rDocXML.GetErrorLineNum();
        }

        if (!bDisplayError)
        {
            if (fileCloseResult != 0)
            {
                // There was a problem closing the stream. We should tell the user
                bDisplayError = true;
                _tcserror_s(strErrorCode.GetBufferSetLength(_MAX_PATH), _MAX_PATH, errno);
                strErrorCode.ReleaseBuffer();
            }
        }
    }

    if (bDisplayError)
    {
        if (iErrorNo == -1)
            iErrorNo = errno;

        strError.Format(IDS_TPL_ERROR_SAVE_XML, strFileXML, strErrorCode, iErrorNo);
        AfxMessageBox(strError, MB_OK | MB_ICONINFORMATION);

        return false;
    }

    return true;
}
  

Как вы можете видеть, все они закрывают поток. Тем не менее, несмотря на то, что в OnDestroy я сначала удаляю представление html, временные файлы по-прежнему не могут быть удалены. Почему?

Ответ №1:

Проблема заключалась в том, как я тестировал файл, который все еще был открыт:

 bool CMeetingScheduleAssistantApp::WaitForFileToBeReady(CString strFile)
{
    HANDLE hFile;
    int delay = 10;

    while ((hFile = CreateFile(strFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_SHARING_VIOLATION) {
            Sleep(delay);
            if (delay < 5120) // max delay approx 5.Sec
                delay *= 2;
        }
        else
        {
            AfxMessageBox(theApp.GetLastErrorAsString(), MB_OK | MB_ICONINFORMATION);
            return false; // some other error occurred
        }
    }

    if (hFile != INVALID_HANDLE_VALUE)
        CloseHandle(hFile);

    return true;
}
  

Мне не хватало CloseHandle строк кода.