Failure to remove folders after using CFileDialog DoModal
-
I picked up a function RecursiveDelete on the internet, as I needed to erase all files and folders on an SD card (as part of a larger project). I was having problems insofar as the function would fail on removing the folders after CFileDialog DoModal - there were two nested folders, the deepest failing with code 32 ("in use by another proicess") and the shallowest with 145 ("folder not empty" - expected !) However, if I call the function BEFORE the DoModal, then everything works fine. I have extracted the relevent code into a simpler project and it still fails Perhaps some kind soul can throw some light on why this is so !!
CFileDialog dlgFileBrowse(true);
UINT uiFileBrowseDlgRC;
// OK here
RecursiveDelete("F:"); // 20150615//
uiFileBrowseDlgRC = dlgFileBrowse.DoModal();// FAILS HERE - YES
void CDeleteFolderTestDlg::RecursiveDelete(CString szPath)
{
CFileFind ff;
BOOL bResult;
CString path = szPath;if(path.Right(1) != '\\\\') path += '\\\\'; path += "\*.\*"; bResult = ff.FindFile(path); BOOL bItemDelete; DWORD dwLastError; CString szFilePath; while(bResult) { bResult = ff.FindNextFile(); if (!ff.IsDots() && !ff.IsDirectory()) { szFilePath = ff.GetFilePath(); bItemDelete = DeleteFile(szFilePath); if(!bItemDelete) dwLastError = GetLastError(); } else if (ff.IsDirectory() && !ff.IsDots()) { path = ff.GetFilePath(); RecursiveDelete(path); bItemDelete = RemoveDirectory(path); if(!bItemDelete) dwLastError = GetLastError(); } }
}
// RecursiveDelete("F:");
Doug
-
I picked up a function RecursiveDelete on the internet, as I needed to erase all files and folders on an SD card (as part of a larger project). I was having problems insofar as the function would fail on removing the folders after CFileDialog DoModal - there were two nested folders, the deepest failing with code 32 ("in use by another proicess") and the shallowest with 145 ("folder not empty" - expected !) However, if I call the function BEFORE the DoModal, then everything works fine. I have extracted the relevent code into a simpler project and it still fails Perhaps some kind soul can throw some light on why this is so !!
CFileDialog dlgFileBrowse(true);
UINT uiFileBrowseDlgRC;
// OK here
RecursiveDelete("F:"); // 20150615//
uiFileBrowseDlgRC = dlgFileBrowse.DoModal();// FAILS HERE - YES
void CDeleteFolderTestDlg::RecursiveDelete(CString szPath)
{
CFileFind ff;
BOOL bResult;
CString path = szPath;if(path.Right(1) != '\\\\') path += '\\\\'; path += "\*.\*"; bResult = ff.FindFile(path); BOOL bItemDelete; DWORD dwLastError; CString szFilePath; while(bResult) { bResult = ff.FindNextFile(); if (!ff.IsDots() && !ff.IsDirectory()) { szFilePath = ff.GetFilePath(); bItemDelete = DeleteFile(szFilePath); if(!bItemDelete) dwLastError = GetLastError(); } else if (ff.IsDirectory() && !ff.IsDots()) { path = ff.GetFilePath(); RecursiveDelete(path); bItemDelete = RemoveDirectory(path); if(!bItemDelete) dwLastError = GetLastError(); } }
}
// RecursiveDelete("F:");
Doug
I assume that the CFileDialog object contains a handle to the directory once it's opened and that the handle is freed when the dialog object is destroyed. You could try the following:
CFileDialog * dialog = new CFileDialog(true);
dialog->DoModal();
delete dialog;
RecursiveDelete("F:");Alternatively you could try:
{
CFileDialog dialog(true);
dialog.DoModal();
}
RecursiveDelete("F:");The good thing about pessimism is, that you are always either right or pleasently surprised.
-
I picked up a function RecursiveDelete on the internet, as I needed to erase all files and folders on an SD card (as part of a larger project). I was having problems insofar as the function would fail on removing the folders after CFileDialog DoModal - there were two nested folders, the deepest failing with code 32 ("in use by another proicess") and the shallowest with 145 ("folder not empty" - expected !) However, if I call the function BEFORE the DoModal, then everything works fine. I have extracted the relevent code into a simpler project and it still fails Perhaps some kind soul can throw some light on why this is so !!
CFileDialog dlgFileBrowse(true);
UINT uiFileBrowseDlgRC;
// OK here
RecursiveDelete("F:"); // 20150615//
uiFileBrowseDlgRC = dlgFileBrowse.DoModal();// FAILS HERE - YES
void CDeleteFolderTestDlg::RecursiveDelete(CString szPath)
{
CFileFind ff;
BOOL bResult;
CString path = szPath;if(path.Right(1) != '\\\\') path += '\\\\'; path += "\*.\*"; bResult = ff.FindFile(path); BOOL bItemDelete; DWORD dwLastError; CString szFilePath; while(bResult) { bResult = ff.FindNextFile(); if (!ff.IsDots() && !ff.IsDirectory()) { szFilePath = ff.GetFilePath(); bItemDelete = DeleteFile(szFilePath); if(!bItemDelete) dwLastError = GetLastError(); } else if (ff.IsDirectory() && !ff.IsDots()) { path = ff.GetFilePath(); RecursiveDelete(path); bItemDelete = RemoveDirectory(path); if(!bItemDelete) dwLastError = GetLastError(); } }
}
// RecursiveDelete("F:");
Doug
When
dlgFileBrowse.DoModal()
returns, the dialog window has been closed but the object itself still exists and may have open file handles. These should be closed by the destructor of the browse dialog. I have not tested this but it seems a probable reason. So you should try to call your delete function after the browse dialog object is destroyed:UINT uiFileBrowseDlgRC;
// This block ensures that dlgFileBrowse goes out of scope
// before calling the delete function.
{
CFileDialog dlgFileBrowse(true);
uiFileBrowseDlgRC = dlgFileBrowse.DoModal();
}
// This should work now.
RecursiveDelete("F:");Alternatively you can create the dialog using
new
and delete it before callingRecursiveDelete
. -
I assume that the CFileDialog object contains a handle to the directory once it's opened and that the handle is freed when the dialog object is destroyed. You could try the following:
CFileDialog * dialog = new CFileDialog(true);
dialog->DoModal();
delete dialog;
RecursiveDelete("F:");Alternatively you could try:
{
CFileDialog dialog(true);
dialog.DoModal();
}
RecursiveDelete("F:");The good thing about pessimism is, that you are always either right or pleasently surprised.
Snap. You beat me by seconds with the solution.
-
I assume that the CFileDialog object contains a handle to the directory once it's opened and that the handle is freed when the dialog object is destroyed. You could try the following:
CFileDialog * dialog = new CFileDialog(true);
dialog->DoModal();
delete dialog;
RecursiveDelete("F:");Alternatively you could try:
{
CFileDialog dialog(true);
dialog.DoModal();
}
RecursiveDelete("F:");The good thing about pessimism is, that you are always either right or pleasently surprised.
Freak30 wrote:
CFileDialog * dialog = new CFileDialog(true); dialog->DoModal(); delete dialog; RecursiveDelete("F:");
Hi Freak30, Tried the dynamic allocation of the CFileDialog (and deletion before the call to RecursiveDelete)as you suggested, but still get the same result (files deleted, but deepest folder gets RC=32 and shallowest gets RC=145. Very confused !!
Doug
-
When
dlgFileBrowse.DoModal()
returns, the dialog window has been closed but the object itself still exists and may have open file handles. These should be closed by the destructor of the browse dialog. I have not tested this but it seems a probable reason. So you should try to call your delete function after the browse dialog object is destroyed:UINT uiFileBrowseDlgRC;
// This block ensures that dlgFileBrowse goes out of scope
// before calling the delete function.
{
CFileDialog dlgFileBrowse(true);
uiFileBrowseDlgRC = dlgFileBrowse.DoModal();
}
// This should work now.
RecursiveDelete("F:");Alternatively you can create the dialog using
new
and delete it before callingRecursiveDelete
.Apologies for the double posting - thought that the original hadn't worked !! Tried dynamic allocation of dialog and subsequent deletion before calling RecursiveDelete as Freak32 suggested, but get exactly the same result. Wierd !! Could someone else run this and see if they can reproduce this behaviour ? (Driving me mad !)
Doug
-
Apologies for the double posting - thought that the original hadn't worked !! Tried dynamic allocation of dialog and subsequent deletion before calling RecursiveDelete as Freak32 suggested, but get exactly the same result. Wierd !! Could someone else run this and see if they can reproduce this behaviour ? (Driving me mad !)
Doug
A quick web research brought some more infomation.
CFileDialog
will change the current working directory which may lead to the locked directory. So you may try to also set the current working directory to something else (e.g. to another drive) before calling your delete function:SetCurrentDirectory(_T("C:\\"));
-
A quick web research brought some more infomation.
CFileDialog
will change the current working directory which may lead to the locked directory. So you may try to also set the current working directory to something else (e.g. to another drive) before calling your delete function:SetCurrentDirectory(_T("C:\\"));
Hi Jochen, Just done a quick check (I actually used _chdir) and that SEEMS to have fixed it. Hopefully, when I migrate these changes to my REAL code, it will stay fixed ! Many thanks to everybody who helped with this - wierd problem, eh ?
Doug
-
Hi Jochen, Just done a quick check (I actually used _chdir) and that SEEMS to have fixed it. Hopefully, when I migrate these changes to my REAL code, it will stay fixed ! Many thanks to everybody who helped with this - wierd problem, eh ?
Doug
Thank you for your feedback.
_chdir
will internally callSetCurrentDirectory
. A directory that is selected as current directory is treated like a file in use and can't be deleted. It seems that the file dialog selects the actually shown directory as the current one and does not change it back. There is anOFN_NOCHANGEDIR
file dialog option to restore the original directory but that is ignored for opening files (only supported for the Save as dialog). -
I picked up a function RecursiveDelete on the internet, as I needed to erase all files and folders on an SD card (as part of a larger project). I was having problems insofar as the function would fail on removing the folders after CFileDialog DoModal - there were two nested folders, the deepest failing with code 32 ("in use by another proicess") and the shallowest with 145 ("folder not empty" - expected !) However, if I call the function BEFORE the DoModal, then everything works fine. I have extracted the relevent code into a simpler project and it still fails Perhaps some kind soul can throw some light on why this is so !!
CFileDialog dlgFileBrowse(true);
UINT uiFileBrowseDlgRC;
// OK here
RecursiveDelete("F:"); // 20150615//
uiFileBrowseDlgRC = dlgFileBrowse.DoModal();// FAILS HERE - YES
void CDeleteFolderTestDlg::RecursiveDelete(CString szPath)
{
CFileFind ff;
BOOL bResult;
CString path = szPath;if(path.Right(1) != '\\\\') path += '\\\\'; path += "\*.\*"; bResult = ff.FindFile(path); BOOL bItemDelete; DWORD dwLastError; CString szFilePath; while(bResult) { bResult = ff.FindNextFile(); if (!ff.IsDots() && !ff.IsDirectory()) { szFilePath = ff.GetFilePath(); bItemDelete = DeleteFile(szFilePath); if(!bItemDelete) dwLastError = GetLastError(); } else if (ff.IsDirectory() && !ff.IsDots()) { path = ff.GetFilePath(); RecursiveDelete(path); bItemDelete = RemoveDirectory(path); if(!bItemDelete) dwLastError = GetLastError(); } }
}
// RecursiveDelete("F:");
Doug
Still learning how to code wrote:
I picked up a function RecursiveDelete on the internet, as I needed to erase all files and folders on an SD card...
Why not just use
SHFileOperation()
with theFO_DELETE
operation?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles