mfcwebbrowser-controlnavigatetourl

CHtmlView::Navigate2 and locked files


I am finding that if I navigate to a file and then I try to delete the file the system tells me it is in use.

How can I stopped the files from being "in use" so I can delete it and recreate it to update the html display?

If I create a NEW XML data file every time and navigate to that then I get no problems. This is because there is no file to delete.

But the moment I use the same file I get the file in use issue.

I added code in my dialog OnDestroy method and added an array of temporary files that i create. Then I try to delete them:

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);
        }
    }
}

I find that ALL of the files are considered still in use.

The code that creates the temporary file names is not the issue:

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;
}

And this is the code that saves my XML files:

bool CMeetingScheduleAssistantApp::SaveToXML(CString strFileXML, tinyxml2::XMLDocument& rDocXML)
{
    FILE    *fStream = nullptr;
    CString strError, strErrorCode;
    errno_t eResult;
    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(&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;
}

As you can see, they all close the stream. Yet, even though in OnDestroy I delete the html view first the temporary files still can't be deleted. Why?


Solution

  • The issue was how I was testing for a file still being open:

    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;
    }
    

    I was missing the CloseHandle lines of code.