【问题标题】:Why is RemoveDirectory function not deleting the top most folder?为什么 RemoveDirectory 函数不删除最顶层的文件夹?
【发布时间】:2012-03-29 20:06:44
【问题描述】:

参考:codeguru.com/forum/showthread.php?t=239271

当使用以下功能删除文件夹时,所有文件夹、子文件夹和文件都将被删除,除了最上面的文件夹。说c:\folder1\folder2路径folder2下的所有东西都被删除除了folder2。

BOOL DeleteDirectory(const TCHAR* sPath)  
{  
    HANDLE hFind; // file handle
    WIN32_FIND_DATA FindFileData;

    TCHAR DirPath[MAX_PATH];
    TCHAR FileName[MAX_PATH];

    _tcscpy(DirPath,sPath);
    _tcscat(DirPath,_T("\\"));
    _tcscpy(FileName,sPath);
    _tcscat(FileName,_T("\\*")); // searching all files
    int nRet = 0;
    hFind = FindFirstFile(FileName, &FindFileData); // find the first file
    if( hFind != INVALID_HANDLE_VALUE ) 
    {
        do
        {
            if( IsDots(FindFileData.cFileName) ) 
                continue; //if not directory continue

            _tcscpy(FileName + _tcslen(DirPath), FindFileData.cFileName);
            if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
            {
                // we have found a directory, recurse
                if( !DeleteDirectory(FileName) ) 
                    break;   // directory couldn't be deleted
            }
            else 
            {
                if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
                    _wchmod(FileName, _S_IWRITE); // change read-only file mode

                if( !DeleteFile(FileName) ) 
                    break;  // file couldn't be deleted
            }
        }while( FindNextFile(hFind, &FindFileData) );

        nRet = FindClose(hFind); // closing file handle
    }

    return RemoveDirectory(sPath); // remove the empty (maybe not) directory and returns zero when RemoveDirectory function fails
}  

感谢您在查找问题方面的任何帮助。 在调试过程中,我注意到FindClose 函数已成功关闭文件句柄,但GetLastError 返回 32(“该进程无法访问该文件,因为它正被另一个进程使用”)但是在尝试使用进程后我没有任何线索探险家。

【问题讨论】:

  • 在 DeleteFile 失败后立即调用 GetLastError 并找出它给出的错误。这应该可以帮助您解决这个问题。

标签: c++ c windows winapi win32-process


【解决方案1】:

虽然您可以通过这种方式删除目录,但通过调用SHFileOperation 传递FO_DELETE 让系统为您执行此操作更简单。请记住,您必须对传递给此 API 的字符串进行双空终止。

【讨论】:

  • 此函数在 Windows Vista 中已被 IFileOperation 替换。我的应用程序需要支持以上所有 Windows 版本,包括 Windows XP。
  • 该功能在Vista中没有被替换。文档是完全错误的。 SHFileOperation 适用于 Win2k、XP、Vista、7。它将适用于 Windows 8。MS 没有删除功能的习惯。一旦他们进来,他们就会留在里面。
  • 我盲目相信 MSDN 文档。感谢 David 抽出宝贵时间。
  • 他们的意思是新的应用程序应该更喜欢使用IFileOperation,它有更多的功能。但是,这样做会使支持 XP 变得很困难,因为您必须使用较旧的 API。如果您不需要新功能,那么使用旧 API 会更容易。
【解决方案2】:

我相信你必须在递归调用之前关闭文件句柄。这意味着退出递归调用后,您必须再次将文件句柄设置为适当的值。

SHFileOperation 可能是更好的解决方案;我只是在回答 OP 的问题,即为什么他们的代码没有按预期工作。

【讨论】:

    【解决方案3】:

    参考:http://www.codeguru.com/forum/archive/index.php/t-337897.html
    下面给出的是使用 SHFileOperation 删除目录的代码

    bool DeleteDirectory(LPCTSTR lpszDir, bool noRecycleBin = true)
    {
        int len = _tcslen(lpszDir);
        TCHAR* pszFrom = new TCHAR[len+4]; //4 to handle wide char
        //_tcscpy(pszFrom, lpszDir); //todo:remove warning//;//convet wchar to char*
        wcscpy_s (pszFrom, len+2, lpszDir);
        pszFrom[len] = 0;
        pszFrom[len+1] = 0;
    
        SHFILEOPSTRUCT fileop;
        fileop.hwnd   = NULL;    // no status display
        fileop.wFunc  = FO_DELETE;  // delete operation
        fileop.pFrom  = pszFrom;  // source file name as double null terminated string
        fileop.pTo    = NULL;    // no destination needed
        fileop.fFlags = FOF_NOCONFIRMATION|FOF_SILENT;  // do not prompt the user
    
        if(!noRecycleBin)
            fileop.fFlags |= FOF_ALLOWUNDO;
    
        fileop.fAnyOperationsAborted = FALSE;
        fileop.lpszProgressTitle     = NULL;
        fileop.hNameMappings         = NULL;
    
        int ret = SHFileOperation(&fileop); //SHFileOperation returns zero if successful; otherwise nonzero 
        delete [] pszFrom;  
        return (0 == ret);
    }
    

    【讨论】:

    猜你喜欢
    • 2018-01-24
    • 2010-09-17
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    • 2010-11-09
    相关资源
    最近更新 更多