2012年12月5日星期三

SHFileOperation.Cpp


/*
删除文件夹有两种办法:
1.递归遍历加RemoveDirectory(移除空目录)。只读属性需要去掉。
2.SHFileOperation函数的FO_DELETE。
修改自:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365200(v=vs.85).aspx等。

If you are writing a 32-bit application to list all the files in a directory and the application may be run on a 64-bit computer,
you should call the Wow64DisableWow64FsRedirectionfunction before calling FindFirstFile and call Wow64RevertWow64FsRedirection after the last call to FindNextFile.
*/

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "User32.lib")

#include "Shlwapi.h"
#pragma comment (lib,"Shlwapi.lib")

#include <locale.h>

void DisplayErrorBox(LPTSTR lpszFunction);

bool deldir(TCHAR * path)
{  
    // Check that the input path plus 3 is not longer than MAX_PATH.
    // Three characters are for the "\*" plus NULL appended below.
    size_t length_of_arg;
    StringCchLength(path, MAX_PATH, &length_of_arg);//argv[1]
    if (length_of_arg > (MAX_PATH - 3))  {
        _tprintf(TEXT("\nDirectory path is too long.\n"));
        return (-1);
    }

    // Prepare string for use with FindFile functions.  First, copy the string to a buffer, then append '\*' to the directory name.
    TCHAR szDir[MAX_PATH];
    StringCchCopy(szDir, MAX_PATH, path);//argv[1]
    StringCchCat(szDir, MAX_PATH, TEXT("\\*"));

    // Find the first file in the directory.
    WIN32_FIND_DATA ffd;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    hFind = FindFirstFile(szDir, &ffd);
    if (INVALID_HANDLE_VALUE == hFind) {
        DisplayErrorBox(TEXT("FindFirstFile"));
        return false;
    }

    // List all the files in the directory with some info about them.
    do
    {
        if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            //_tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);
            if (lstrcmpi(ffd.cFileName,L".") == 0 ||
                lstrcmpi(ffd.cFileName,L"..") == 0)
            {
                //这里不操作。
            }
            else
            {
                TCHAR sztemp[MAX_PATH] = {0};
                StringCchCopy(sztemp, MAX_PATH, path);//argv[1]
                PathAppend(sztemp, ffd.cFileName);
                deldir(sztemp);

                /*_tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);*/
            }
        }
        else
        {
            //LARGE_INTEGER filesize;//这几行显示信息用的,无实际用途。
            //filesize.LowPart = ffd.nFileSizeLow;
            //filesize.HighPart = ffd.nFileSizeHigh;
            //_tprintf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);

            TCHAR sztemp[MAX_PATH] = {0};
            StringCchCopy(sztemp, MAX_PATH, path);//argv[1]
            PathAppend(sztemp, ffd.cFileName);
            bool b = DeleteFile(sztemp);
            if (b == 0)
            {
                int x = GetLastError();
                x = x;//查看x的值用的。
            }
        }
    } while (FindNextFile(hFind, &ffd) != 0);

    //dwError = GetLastError();
    //if (dwError != ERROR_NO_MORE_FILES) {
    //    DisplayErrorBox(TEXT("FindFirstFile"));
    //}

    FindClose(hFind);

    return RemoveDirectory(path);//里面有空文件夹依旧任务是空目录。返回0失败。
}

void DelDir2(TCHAR * dir)
{
    if (!PathFileExists(dir))
    {
        return;
    }

    TCHAR DelDir[MAX_PATH] = {0};
    lstrcpy(DelDir,dir);
    int len = lstrlen(dir);
    DelDir[len] = 0;
    DelDir[len+1] = 0;

    SHFILEOPSTRUCT FileOp;
    ZeroMemory((void*)&FileOp, sizeof(SHFILEOPSTRUCT));

    FileOp.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
    FileOp.hNameMappings = NULL;
    FileOp.hwnd = NULL;
    FileOp.lpszProgressTitle = NULL;
    FileOp.pFrom = DelDir;
    FileOp.pTo = NULL;
    FileOp.wFunc = FO_DELETE;

    int err = SHFileOperation(&FileOp);
    if (0 != err)
    {
        //失败。
    }
}

int _tmain(int argc, TCHAR *argv[])
{
    setlocale(LC_CTYPE, ".936");

    TCHAR path[MAX_PATH] = L"e:\\test";

    bool b = deldir(path);

    DelDir2(L"e:\\test2");

    return 0;
}

void DisplayErrorBox(LPTSTR lpszFunction) //这个函数封装的还不错的,以后就拿来用吧!
{
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    DWORD dw = GetLastError();

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );

    // Display the error message and clean up
    LPVOID lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
    StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

没有评论:

发表评论