路径操作(Win32, C++)

CPathUtils是一个C++类,包含了多种与文件路径相关的操作,如获取当前进程路径、文件属性、文件大小、重命名、移动、拷贝、删除等,同时也支持长路径和短路径之间的转换。此外,它还提供了获取磁盘空间、遍历目录等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CPathUtils.h

#pragma once

#include <wtypesbase.h>
#include <tchar.h>
#include <string>
#include <vector>
#include <map>
#include <functional>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

namespace CPathUtils
{
    typedef struct _FILEINFO
    {
        _tstring m_filePath;
        unsigned long long m_fileSize;
        DWORD m_fileAttributes;
        unsigned long long m_ftCreationTime;
        unsigned long long m_ftLastAccessTime;
        unsigned long long m_ftLastWriteTime;

        _FILEINFO() :
            m_fileSize(0),
            m_fileAttributes(0),
            m_ftCreationTime(0),
            m_ftLastAccessTime(0),
            m_ftLastWriteTime(0)
        {

        };
    }FILEINFO;

    // 
    // @brief: 获取当前进程完全路径
    // @ret: 当前进程完全路径 如 D:\Software\HxDPortableSetup.exe
    _tstring GetCurrentModulePath();

    // 
    // @brief: 获取当前进程所在目录
    // @ret: 当前进程所在目录 如 D:\Software
    _tstring GetCurrentModuleDir();

    // 
    // @brief: 获取当前进程名
    // @ret: 当前进程名 如 HxDPortableSetup.exe
    _tstring GetCurrentModuleName(bool bHasExt = false);

    // 
    // @brief: 获取文件所在驱动器
    // @param: strPath     文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 文件夹        如 D:
    _tstring GetFileDriver(const _tstring& strPath);

    // 
    // @brief: 获取文件所在文件夹
    // @param: strPath     文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 文件夹        如 D:\Software
    _tstring GetFileDir(const _tstring& strPath);

    // 
    // @brief: 获取文件名
    // @param: strPath     文件名, 如: D:\Software\HxDPortableSetup.exe
    // @param: bHasExt     是否包含扩展名
    // @ret: 文件夹        如 HxDPortableSetup
    _tstring GetFileName(const _tstring& strPath, bool bHasExt = false);

    // 
    // @brief: 获取文件扩展名
    // @param: strPath     文件名, 如: D:\Software\HxDPortableSetup.exe
    // @param: bHasDot     是否包含点号
    // @ret: 文件夹        如 exe
    _tstring GetFileExt(const _tstring& strPath, bool bHasDot = false);

    // 
    // @brief: 获取短路径
    // @param: strPath     输入长路径(必须存在)
    // @ret: 短路径
    _tstring GetShortPath(const _tstring& strPath);

    // 
    // @brief: 获取长路径
    // @param: strPath     输入短路径(必须存在)
    // @ret: 长路径
    _tstring GetLongPath(const _tstring& strPath);

    // 
    // @brief: 获取全路径
    // @param: strPath     输入路径
    // @ret: 全路径
    _tstring GetFullPath(const _tstring& strPath);

    //
    // @brief: DOS路径转Nt路径
    // @param: strPath      路径
    // @ret: _tstring       Win32 样式的 NT 路径
    _tstring DosPathToNtPath(const _tstring& strPath);

    //
    // @brief: Nt路径转DOS路径
    // @param: strPath      路径
    // @ret: _tstring       DOS路径
    _tstring NtPathToDosPath(const _tstring& strPath);

    //
    // @brief: 获取路径属性
    // @param: strPath      路径
    // @ret: DWORD          属性
    bool GetAttributes(const _tstring& strPath, DWORD& dwAttr);
    DWORD GetAttributes(const _tstring& strPath);

    //
    // @brief: 设置路径属性
    // @param: strPath      路径
    // @ret: 成功返回true
    bool SetAttributes(const _tstring& strPath, const DWORD& dwAttr);

    //
    // @brief: 获取文件大小
    // @param: strPath      路径
    // @ret: 文件大小
    unsigned long long GetFileSize(const _tstring& strPath);

    // 
    // @brief: 检查是否为文件
    // @param: strPath      文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 是否存在       存在返回 true
    bool IsFile(const _tstring& strPath);

    // 
    // @brief: 检查是否为文件夹
    // @param: strPath      文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 是否存在       存在返回 true
    bool IsDirectory(const _tstring& strPath);

    // 
    // @brief: 检查路径是否存在
    // @param: strPath      文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 是否存在       存在返回 true
    bool IsExist(const _tstring& strPath);

    // 
    // @brief: 检查路径是否隐藏
    // @param: strPath      文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 是否存在       存在返回 true
    bool IsHidden(const _tstring& strPath);

    // 
    // @brief: 检查路径是否只读
    // @param: strPath      文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 是否存在       只读返回 true
    bool IsReadonly(const _tstring& strPath);

    // 
    // @brief: 判断是否是完整路径
    // @param: strPath      文件名, 如: D:\Software\HxDPortableSetup.exe
    // @ret: 是返回 true
    bool IsFullPath(const _tstring& strPath);

    // 
    // @brief: 获取从 strSrc 到 strDest 的相对路径
    // @param: strDest      路径目标
    // @param: strSrc       基于路径源
    // @ret: 是返回 _tstring   相对路径
    _tstring GetRelativePath(const _tstring& strDest, const _tstring& strSrc, bool bFromIsDir = true);

    // 
    // @brief: 判断是否是相对路径
    // @param: strPath
    // @ret: 是返回 true
    bool IsRelative(const _tstring& strPath);

    // 
    // @brief: 判断是否是绝路径
    // @param: strPath
    // @ret: 是返回 true
    bool IsAbsolutePath(const _tstring& strPath);

    // 
    // @brief: 如果路径存在空格, 则使用引号括起来
    // @param: strPath      文件名, 如: C:\Program Files (x86)
    // @ret: 添加引号       添加引号返回 true
    bool QuoteSpaces(_tstring& strPath);

    // 
    // @brief: 删除路径开头和末尾的引号
    // @param: strPath      文件名, 如: "C:\Program Files (x86)"
    // @ret: 去除引号       去除引号返回 true
    bool UnquoteSpaces(_tstring& strPath);

    //
    // @brief: 获取相对路径的绝对路径
    // @param: strPath      文件(夹)相对路径
    // @ret: _tstring       转换后的绝对路径
    _tstring GetAbsolutePath(const _tstring& strPath);

    //
    // @brief: 获取读取工作路径的绝对路径
    // @param: strPath      文件(夹)相对路径
    // @ret: _tstring       转换后的绝对路径
    _tstring GetCurrentAbsolutePath(const _tstring& strPath);

    //
    // @brief: 重命名(夹)
    // @param: strSrc       原始文件名
    // @param: strDest      目标文件名(绝对路径或仅目标名)
    // @ret: 成功返回true
    bool Rename(const _tstring& strSrc, const _tstring& strDest);

    //
    // @brief: 移动文件(夹)
    // @param: strSrc       原始文件名
    // @param: strDest      目标文件名(绝对路径或仅目标名)
    // @ret: 成功返回true
    bool Move(const _tstring& strSrc, const _tstring& strDest);

    //
    // @brief: 拷贝文件(夹)
    // @param: strSrc       源路径
    // @param: strDest      目的路径(末尾为'\'则认为是复制到文件夹)
    // @param: bEmptyDir    是否拷贝空文件夹
    // @param: bOverwrites  是否覆盖文件
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @ret: 成功返回true
    bool Copy(
        const _tstring& strSrc,
        const _tstring& strDest,
        bool bEmptyDir = true,
        bool bOverwrites = false,
        int32_t depth = MAX_PATH
    );

    //
    // @brief: 拷贝文件夹
    // @param: strSrc       源文件夹
    // @param: strDest      目的文件夹
    // @param: bEmptyDir    是否拷贝空文件夹
    // @param: bOverwrites  是否覆盖文件
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @ret: 成功返回true
    bool CopyDir(
        const _tstring& strSrc,
        const _tstring& strDest,
        bool bEmptyDir = true,
        bool bOverwrites = false,
        int32_t depth = MAX_PATH
    );

    //
    // @brief: 删除文件或文件夹
    // @param: strPath      路径
    // @ret: 成功返回true
    bool Delete(const _tstring& strPath);

    //
    // @brief: 删除文件
    // @param: strPath      路径
    // @ret: 成功返回true
    bool DeleteArchive(const _tstring& strPath);

    //
    // @brief: 删除目录(递归删除子目录及文件)
    // @param: strPath      路径
    // @param: bSubOnly     仅删除子项
    // @ret: 成功返回true
    bool DeleteDir(const _tstring& strPath, bool bSubOnly = false);

    //
    // @brief: 创建目录(递归)
    // @param: strPath      路径
    // @ret: 成功返回true
    bool CreateDir(const _tstring& strPath);

    //
    // @brief: 拷贝文件(夹)(使用SHFileOperation)
    // @param: strSrcPath   源路径
    // @param: strDestPath  目的路径(末尾为'\'则认为是复制到文件夹)
    // @ret: 错误代码       成功返回0
    int SHCopy(const _tstring& strSrc, const _tstring& strDest);

    //
    // @brief: 重命名(夹)(使用SHFileOperation)
    // @param: strSrc       原始文件名
    // @param: strDest      目标文件名(绝对路径或仅目标名)
    // @ret: 错误代码       成功返回0
    int SHMove(const _tstring& strSrc, const _tstring& strDest);

    //
    // @brief: 移动文件(夹)(使用SHFileOperation)
    // @param: strSrc       原始文件名
    // @param: strDest      目标文件名(绝对路径或仅目标名)
    // @ret: 错误代码       成功返回0
    int SHRename(const _tstring& strSrc, const _tstring& strDest);

    //
    // @brief: 删除文件(使用SHFileOperation)
    // @param: strPath      路径
    // @ret: 错误代码       成功返回0
    int SHDelete(const _tstring& strSrc);

    //
    // @brief: 获取展开环境变量字符串
    // @param: strPath      路径
    // @ret: _tstring       展开字符串
    _tstring GetExpandEnvStrings(const _tstring& strPath);

    //
    // @brief: 获取环境变量字符串
    // @param: strPath      路径
    // @ret: _tstring       展开字符串
    _tstring GetUnExpandEnvStrings(const _tstring& strPath);

    //
    // @brief: 获取目录下文件路径
    // @param: strDir       指定目录
    // @param: extList      扩展名过滤列表, 如: {("exe"), ("txt")}
    // @param: bIncludeHide 是否包含隐藏文件
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @ret: std::vector<_tstring> 文件路径列表
    std::vector<_tstring> GetPathList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取工作目录下文件路径
    // @param: strDir       指定目录
    // @param: extList      扩展名过滤列表, 如: {("exe"), ("txt")}
    // @param: bIncludeHide 是否包含隐藏文件
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @ret: std::vector<_tstring> 文件路径列表
    std::vector<_tstring> GetCurrentPathList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取目录下文件路径
    // @param: strDir       指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: dwExclude    排除属性
    // @param: dwContain    包含属性
    std::vector<FILEINFO> GetFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取工作目录下文件路径
    // @param: strDir       指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: dwExclude    排除属性
    // @param: dwContain    包含属性
    std::vector<FILEINFO> GetCurrentFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取目录下文件路径
    // @param: strDir       指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: dwExclude    排除属性
    // @param: dwContain    包含属性
    std::map<_tstring, FILEINFO> GetPathAndFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取工作目录下文件路径
    // @param: strDir       指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: dwExclude    排除属性
    // @param: dwContain    包含属性
    std::map<_tstring, FILEINFO> GetCurrentPathAndFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取符合搜索要求的文件路径
    // @param: strDir       指定目录
    // @param: strSrcName   指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: dwExclude    排除属性
    // @param: dwContain    包含属性
    std::vector<_tstring> SearchFiles(
        const _tstring& strDir,
        const _tstring& strSrcName,
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    //
    // @brief: 获取磁盘卷可用空间
    // @param: strDir       指定目录, 如 "C:\"
    // @ret: ULONGLONG      可用空间
    ULONGLONG GetDiskFreeSize(const _tstring& strDir);

    //
    // @brief: 获取磁盘卷总空间
    // @param: strDir       指定目录, 如 "C:\"
    // @ret: ULONGLONG      总空间
    ULONGLONG GetDiskTotalSize(const _tstring& strDir);

    // 已知文件夹获取
    _tstring GetNetworkFolder();
    _tstring GetComputerFolder();
    _tstring GetInternetFolder();
    _tstring GetControlPanelFolder();
    _tstring GetPrintersFolder();
    _tstring GetSyncManagerFolder();
    _tstring GetSyncSetupFolder();
    _tstring GetConflictFolder();
    _tstring GetSyncResultsFolder();
    _tstring GetRecycleBinFolder();
    _tstring GetConnectionsFolder();
    _tstring GetFonts();
    _tstring GetDesktop();
    _tstring GetStartup();
    _tstring GetPrograms();
    _tstring GetStartMenu();
    _tstring GetRecent();
    _tstring GetSendTo();
    _tstring GetDocuments();
    _tstring GetFavorites();
    _tstring GetNetHood();
    _tstring GetPrintHood();
    _tstring GetTemplates();
    _tstring GetCommonStartup();
    _tstring GetCommonPrograms();
    _tstring GetCommonStartMenu();
    _tstring GetPublicDesktop();
    _tstring GetProgramData();
    _tstring GetCommonTemplates();
    _tstring GetPublicDocuments();
    _tstring GetRoamingAppData();
    _tstring GetLocalAppData();
    _tstring GetLocalAppDataLow();
    _tstring GetInternetCache();
    _tstring GetCookies();
    _tstring GetHistory();
    _tstring GetSystem();
    _tstring GetSystemX86();
    _tstring GetWindows();
    _tstring GetProfile();
    _tstring GetPictures();
    _tstring GetProgramFilesX86();
    _tstring GetProgramFilesCommonX86();
    _tstring GetProgramFilesX64();
    _tstring GetProgramFilesCommonX64();
    _tstring GetProgramFiles();
    _tstring GetProgramFilesCommon();
    _tstring GetUserProgramFiles();
    _tstring GetUserProgramFilesCommon();
    _tstring GetAdminTools();
    _tstring GetCommonAdminTools();
    _tstring GetMusic();
    _tstring GetVideos();
    _tstring GetRingtones();
    _tstring GetPublicPictures();
    _tstring GetPublicMusic();
    _tstring GetPublicVideos();
    _tstring GetPublicRingtones();
    _tstring GetResourceDir();
    _tstring GetLocalizedResourcesDir();
    _tstring GetCommonOEMLinks();
    _tstring GetCDBurning();
    _tstring GetUserProfiles();
    _tstring GetPlaylists();
    _tstring GetSamplePlaylists();
    _tstring GetSampleMusic();
    _tstring GetSamplePictures();
    _tstring GetSampleVideos();
    _tstring GetPhotoAlbums();
    _tstring GetPublic();
    _tstring GetChangeRemovePrograms();
    _tstring GetAppUpdates();
    _tstring GetAddNewPrograms();
    _tstring GetDownloads();
    _tstring GetPublicDownloads();
    _tstring GetSavedSearches();
    _tstring GetQuickLaunch();
    _tstring GetContacts();
    _tstring GetSidebarParts();
    _tstring GetSidebarDefaultParts();
    _tstring GetPublicGameTasks();
    _tstring GetGameTasks();
    _tstring GetSavedGames();
    _tstring GetGames();
    _tstring GetSEARCH_MAPI();
    _tstring GetSEARCH_CSC();
    _tstring GetLinks();
    _tstring GetUsersFiles();
    _tstring GetUsersLibraries();
    _tstring GetSearchHome();
    _tstring GetOriginalImages();
    _tstring GetDocumentsLibrary();
    _tstring GetMusicLibrary();
    _tstring GetPicturesLibrary();
    _tstring GetVideosLibrary();
    _tstring GetRecordedTVLibrary();
    _tstring GetHomeGroup();
    _tstring GetHomeGroupCurrentUser();
    _tstring GetDeviceMetadataStore();
    _tstring GetLibraries();
    _tstring GetPublicLibraries();
    _tstring GetUserPinned();
    _tstring GetImplicitAppShortcuts();
    _tstring GetAccountPictures();
    _tstring GetPublicUserTiles();
    _tstring GetAppsFolder();
    _tstring GetStartMenuAllPrograms();
    _tstring GetCommonStartMenuPlaces();
    _tstring GetApplicationShortcuts();
    _tstring GetRoamingTiles();
    _tstring GetRoamedTileImages();
    _tstring GetScreenshots();
    _tstring GetCameraRoll();
    _tstring GetSkyDrive();
    _tstring GetOneDrive();
    _tstring GetSkyDriveDocuments();
    _tstring GetSkyDrivePictures();
    _tstring GetSkyDriveMusic();
    _tstring GetSkyDriveCameraRoll();
    _tstring GetSearchHistory();
    _tstring GetSearchTemplates();
    _tstring GetCameraRollLibrary();
    _tstring GetSavedPictures();
    _tstring GetSavedPicturesLibrary();
    _tstring GetRetailDemo();
    _tstring GetDevice();
    _tstring GetDevelopmentFiles();
    _tstring GetObjects3D();
    _tstring GetAppCaptures();
    _tstring GetLocalDocuments();
    _tstring GetLocalPictures();
    _tstring GetLocalVideos();
    _tstring GetLocalMusic();
    _tstring GetLocalDownloads();
    _tstring GetRecordedCalls();
    _tstring GetAllAppMods();
    _tstring GetCurrentAppMods();
    _tstring GetAppDataDesktop();
    _tstring GetAppDataDocuments();
    _tstring GetAppDataFavorites();
    _tstring GetAppDataProgramData();
}

CPathUtils.cpp

#include "CPathUtils.h"
#include <windows.h>
#include <shlwapi.h>
#include <io.h>

#include <shlobj_core.h>
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Shlwapi.lib")

namespace CPathUtils
{
    void _GetPathListEx(
        const _tstring& dir,
        std::function<bool(const _tstring strPath, const WIN32_FIND_DATA& findData)> cb,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    void _GetPathList(
        std::vector<_tstring>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    void _GetFileInfoList(
        std::vector<FILEINFO>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    void _GetPathAndPathInfoList(
        std::map<_tstring, FILEINFO>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    void _SearchFiles(
        std::vector<_tstring>& fileList,
        const _tstring& strSrcDir,
        const _tstring& strSrcName,
        int32_t depth = MAX_PATH,
        DWORD dwExclude = 0,
        DWORD dwContain = 0
    );

    _tstring GetCurrentModulePath()
    {
        TCHAR szCurPath[MAX_PATH] = { 0 };
        ::GetModuleFileName(NULL, szCurPath, _countof(szCurPath));
        return szCurPath;
    }

    _tstring GetCurrentDir()
    {
        TCHAR szCurPath[MAX_PATH] = { 0 };
        ::GetCurrentDirectory(_countof(szCurPath), szCurPath);
        return szCurPath;
    }

    _tstring GetCurrentModuleDir()
    {
        return GetFileDir(GetCurrentModulePath());
    }

    _tstring GetCurrentModuleName(bool bHasExt/* = false*/)
    {
        return GetFileName(GetCurrentModulePath(), bHasExt);
    }

    _tstring GetFileDriver(const _tstring& strPath)
    {
        _tstring strResult;
        if (strPath.size() > 2 && _T(':') == strPath[1])
        {
            strResult = strPath.substr(0, 1);
        }

        return strResult;
    }

    _tstring GetFileDir(const _tstring& strPath)
    {
        _tstring strDir = strPath;
        for (auto& ch : strDir)
        {
            if (_T('/') == ch)
            {
                ch = _T('\\');
            }
        }

        _tstring strResult;
        size_t nIndex = strDir.find_last_of(_T('\\'));
        if (nIndex != _tstring::npos)
        {
            strResult = strDir.substr(0, nIndex);
        }

        return strResult;
    }

    _tstring GetFileName(const _tstring& strPath, bool bHasExt/* = false*/)
    {
        _tstring strResult = strPath;
        size_t nIndex = strResult.find_last_of(_T('\\'));
        if (nIndex != _tstring::npos)
        {
            strResult = strResult.substr(nIndex + 1);
        }

        if (!bHasExt)
        {
            nIndex = strResult.find_last_of(_T('.'));
            if (nIndex != _tstring::npos)
            {
                strResult.resize(nIndex);
            }
        }

        return strResult;
    }

    _tstring GetFileExt(const _tstring& strPath, bool bHasDot/* = false*/)
    {
        _tstring strResult = strPath;
        size_t nIndex = strResult.find_last_of(_T('.'));
        if (nIndex != _tstring::npos)
        {
            if (bHasDot)
            {
                strResult = strResult.substr(nIndex);
            }
            else
            {
                strResult = strResult.substr(nIndex + 1);
            }
        }
        else
        {
            strResult = _T("");
        }

        return strResult;
    }

    _tstring GetShortPath(const _tstring& strPath)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::GetShortPathName(strPath.c_str(), szBuf, _countof(szBuf));
        return szBuf;
    }

    _tstring GetLongPath(const _tstring& strPath)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::GetLongPathName(strPath.c_str(), szBuf, _countof(szBuf));
        return szBuf;
    }

    _tstring GetFullPath(const _tstring& strPath)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        TCHAR* pFilePart = nullptr;
        ::GetFullPathName(strPath.c_str(), _countof(szBuf), szBuf, &pFilePart);
        return szBuf;
    }

    _tstring DosPathToNtPath(const _tstring& strPath)
    {
        _tstring strResultPath;
        TCHAR szDriveStrings[MAX_PATH] = { 0 };
        TCHAR szDosBuf[MAX_PATH] = { 0 };
        LPTSTR pDriveStr = NULL;

        do
        {
            // 获取盘符名到缓冲
            if (!::GetLogicalDriveStrings(_countof(szDriveStrings), szDriveStrings))
            {
                break;
            }

            // 遍历盘符名
            for (int i = 0; i < _countof(szDriveStrings); i += 4)
            {
                pDriveStr = &szDriveStrings[i];
                pDriveStr[2] = _T('\0');

                // 查询盘符对应的DOS设备名称
                DWORD dwCch = ::QueryDosDevice(pDriveStr, szDosBuf, _countof(szDosBuf));
                if (!dwCch)
                {
                    break;
                }

                // 结尾有 2 个 NULL, 减去 2 获得字符长度
                if (dwCch >= 2)
                {
                    dwCch -= 2;
                }

                if (strPath.size() < dwCch)
                {
                    break;
                }

                // 路径拼接
                if (_T('\\') == strPath[dwCch] && 0 == _tcsncmp(strPath.c_str(), szDosBuf, dwCch))
                {
                    strResultPath = pDriveStr;
                    strResultPath += &strPath[dwCch];
                    break;
                }
            }

        } while (false);

        return strResultPath;
    }

    _tstring NtPathToDosPath(const _tstring& strPath)
    {
        _tstring strResultPath;
        TCHAR szDosBuf[MAX_PATH] = { 0 };

        do
        {
            if (strPath.size() < 2)
            {
                break;
            }

            // 非 NT 路径则不处理
            if (_T(':') != strPath[1] || _T('\\') == strPath[0])
            {
                break;
            }

            // 查询盘符对应的DOS设备名称
            if (!::QueryDosDevice(strPath.substr(0, 2).c_str(), szDosBuf, _countof(szDosBuf)))
            {
                break;
            }

            strResultPath = szDosBuf;
            strResultPath += strPath.substr(2);

        } while (false);

        return strResultPath;
    }

    bool GetAttributes(const _tstring& strPath, DWORD& dwAttr)
    {
        WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
        if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
        {
            return false;
        }

        dwAttr = attr.dwFileAttributes;
        return true;
    }

    DWORD GetAttributes(const _tstring& strPath)
    {
        WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
        if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
        {
            return 0;
        }

        return attr.dwFileAttributes;
    }

    bool SetAttributes(const _tstring& strPath, const DWORD& dwAttr)
    {
        return ::SetFileAttributes(strPath.c_str(), dwAttr);
    }

    unsigned long long GetFileSize(const _tstring& strPath)
    {
        unsigned long long ullSize = 0;
        WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
        if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
        {
            return 0;
        }

        if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            return 0;
        }

        ullSize = (unsigned long long)attr.nFileSizeHigh << 32 | attr.nFileSizeLow;

        return ullSize;
    }

    bool IsFile(const _tstring& strPath)
    {
        DWORD dwAttr = 0;
        if (!GetAttributes(strPath, dwAttr))
        {
            return false;
        }

        return 0 == (dwAttr & FILE_ATTRIBUTE_DIRECTORY);
    }

    bool IsDirectory(const _tstring& strPath)
    {
        return 0 != (GetAttributes(strPath) & FILE_ATTRIBUTE_DIRECTORY);
    }

    bool IsExist(const _tstring& strPath)
    {
        return 0 == _taccess_s(strPath.c_str(), 00);
    }

    bool IsReadonly(const _tstring& strPath)
    {
        return 0 != (GetAttributes(strPath) & FILE_ATTRIBUTE_READONLY);
    }

    bool IsHidden(const _tstring& strPath)
    {
        WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
        if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
        {
            return false;
        }

        return attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN;
    }

    bool IsFullPath(const _tstring& strPath)
    {
        if (::PathIsRelative(strPath.c_str()) || ::PathIsUNC(strPath.c_str()))
        {
            return false;
        }

        return true;
    }

    _tstring GetRelativePath(const _tstring& strDest, const _tstring& strSrc, bool bFromIsDir/* = true*/)
    {
        _TCHAR szRelativePath[MAX_PATH] = { 0 };
        DWORD dwAttrFrom = 0;

        if (bFromIsDir)
        {
            dwAttrFrom = FILE_ATTRIBUTE_DIRECTORY;
        }

        if (::PathRelativePathTo(szRelativePath, strSrc.c_str(), dwAttrFrom, strDest.c_str(), 0))
        {
            return szRelativePath;
        }

        return strDest;
    }

    bool IsRelative(const _tstring& strPath)
    {
        return ::PathIsRelative(strPath.c_str());
    }

    bool IsAbsolutePath(const _tstring& strPath)
    {
        return !::PathIsRelative(strPath.c_str());
    }

    bool QuoteSpaces(_tstring& strPath)
    {
        if (strPath.empty())
        {
            return false;
        }

        size_t nFindBegin = strPath.find_first_of(_T('\"'));
        size_t nFindEnd = strPath.find_last_of(_T('\"'));

        //两边已经有引号
        if (0 == nFindBegin && (strPath.size() - 1 == nFindEnd))
        {
            return false;
        }

        //检查是否有空格
        if (_tstring::npos == strPath.find(_T(' ')))
        {
            return false;
        }

        strPath = _T("\"") + strPath + _T("\"");
        return true;
    }

    bool UnquoteSpaces(_tstring& strPath)
    {
        size_t nFindBegin = strPath.find_first_of(_T('\"'));
        size_t nFindEnd = strPath.find_last_of(_T('\"'));

        if (_tstring::npos == nFindBegin || _tstring::npos == nFindEnd)
        {
            return false;
        }

        strPath = strPath.substr(nFindBegin + 1, strPath.size() - 2);

        return true;
    }

    _tstring GetAbsolutePath(const _tstring& strPath)
    {
        _tstring strResult = strPath;
        if (PathIsRelative(strPath.c_str()))
        {
            if (strPath.empty())
            {
                strResult = GetCurrentModuleDir();
            }
            else
            {
                strResult = GetCurrentModuleDir() + _T("\\") + strPath;
            }
        }

        return strResult;
    }

    _tstring GetCurrentAbsolutePath(const _tstring& strPath)
    {
        _tstring strResult = strPath;
        if (PathIsRelative(strPath.c_str()))
        {
            if (strPath.empty())
            {
                strResult = GetCurrentDir();
            }
            else
            {
                strResult = GetCurrentDir() + _T("\\") + strPath;
            }
        }

        return strResult;
    }

    bool Rename(const _tstring& strSrc, const _tstring& strDest)
    {
        return Move(strSrc, strDest);
    }

    bool Move(const _tstring& strSrc, const _tstring& strDest)
    {
        _tstring strSrcPath = strSrc;
        _tstring strDestPath = strDest;

        //不存在则提前返回
        if (!IsExist(strSrcPath))
        {
            return false;
        }

        strSrcPath = GetAbsolutePath(strSrc);
        strDestPath = GetAbsolutePath(strDest);

        _tstring strSrcName = GetFileName(strSrc, true);
        _tstring strDestDir = GetFileDir(strDestPath);

        //末尾为反斜杠则认为是移动到文件夹内
        if (_T('\\') == strDestPath.back())
        {
            strDestPath += strSrcName;
        }

        //检查目标文件夹, 不存在则创建
        if (!IsDirectory(strDestDir))
        {
            CreateDir(strDestDir);
        }

        return ::MoveFileEx(strSrcPath.c_str(), strDestPath.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
    }

    bool Copy(
        const _tstring& strSrc,
        const _tstring& strDest,
        bool bEmptyDir/* = true*/,
        bool bOverwrites/* = false*/,
        int32_t depth/* = MAX_PATH*/
    )
    {
        //到达深度限制返回
        if (depth < 0)
        {
            return true;
        }

        if (strSrc.empty() || strDest.empty())
        {
            return false;
        }

        _tstring strSrcName = GetFileName(strSrc, true);

        // 文件拷贝
        if (IsFile(strSrc))
        {
            // 拷贝到目录
            if (_T('\\') == strDest.back())
            {
                _tstring strDir = strDest.substr(0, strDest.size() - 1);
                _tstring strFile = strDest + strSrcName;
                if (!strDir.empty() && !IsDirectory(strDir))
                {
                    CreateDir(strDir);
                }

                if (!bOverwrites && IsFile(strFile))
                {
                    return true;
                }

                return ::CopyFile(strSrc.c_str(), strFile.c_str(), FALSE);
            }
            else
            {
                _tstring strDestDir = strDest;
                _tstring strDestName = strSrcName;

                if (!IsDirectory(strDest))
                {
                    strDestDir = GetFileDir(strDest);
                    strDestName = GetFileName(strDest, true);
                }

                if (!strDestDir.empty() && !IsDirectory(strDestDir))
                {
                    CreateDir(strDestDir);
                }

                _tstring strDestFile = strDestName;
                if (!strDestDir.empty())
                {
                    strDestFile = strDestDir + _T("\\") + strDestName;
                }

                if (!bOverwrites && IsFile(strDestFile))
                {
                    return true;
                }

                return ::CopyFile(strSrc.c_str(), strDestFile.c_str(), FALSE);
            }
        }
        else
        {
            // 不是文件夹且所在文件夹不存在则认为失败
            if (!IsDirectory(strSrc) && !IsDirectory(GetFileDir(strSrc)))
            {
                return false;
            }

            _tstring strCopyDest = strDest;
            if (IsDirectory(strSrc) && _T('\\') == strCopyDest.back())
            {
                strCopyDest = strDest + strSrcName;
            }

            return CopyDir(strSrc, strCopyDest, bEmptyDir, bOverwrites, depth);
        }

        return false;
    }

    bool CopyDir(
        const _tstring& strSrc,
        const _tstring& strDest,
        bool bEmptyDir/* = true*/,
        bool bOverwrites/* = false*/,
        int32_t depth/* = MAX_PATH*/
    )
    {
        //到达深度限制返回
        if (depth < 0)
        {
            return true;
        }

        WIN32_FIND_DATA findData = { 0 };
        HANDLE hFindHandle = INVALID_HANDLE_VALUE;

        _tstring strFindName;
        _tstring strFindFile = strSrc;
        _tstring strFindDir = strSrc;

        //文件夹则匹配全部类型文件
        if (IsDirectory(strSrc))
        {
            strFindFile = strSrc + _T("\\*");
        }
        else
        {
            strFindDir = GetFileDir(strSrc);
            strFindName = GetFileName(strSrc, true);
        }

        if (!IsDirectory(strFindDir))
        {
            return false;
        }

        //先拷贝符合规则的文件
        do
        {
            hFindHandle = FindFirstFile(strFindFile.c_str(), &findData);
            if (INVALID_HANDLE_VALUE == hFindHandle)
            {
                break;
            }

            do
            {
                //上一级目录与当前目录跳过
                if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
                {
                    continue;
                }

                //拷贝文件
                if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                {
                    _tstring strPathTo = strDest + _T("\\") + findData.cFileName;
                    if (!IsDirectory(strDest))
                    {
                        CreateDir(strDest);
                    }

                    _tstring strFileFrom = strFindDir + _T("\\") + findData.cFileName;

                    if (!bOverwrites && IsFile(strPathTo))
                    {
                        return true;
                    }

                    ::CopyFile(strFileFrom.c_str(), strPathTo.c_str(), FALSE);
                }
            } while (::FindNextFile(hFindHandle, &findData));

            ::FindClose(hFindHandle);

        } while (false);

        //后拷贝文件夹
        do
        {
            hFindHandle = FindFirstFile((strFindDir + _T("\\*")).c_str(), &findData);
            if (INVALID_HANDLE_VALUE == hFindHandle)
            {
                break;
            }

            do
            {
                //上一级目录与当前目录跳过
                if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
                {
                    continue;
                }

                //拷贝文件
                if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                {
                    _tstring strPathTo = strDest + _T("\\") + findData.cFileName;
                    if (bEmptyDir && !IsDirectory(strPathTo))
                    {
                        CreateDir(strPathTo);
                    }

                    _tstring strFileFrom = strFindDir + _T("\\") + findData.cFileName;

                    if (strFindName.empty())
                    {
                        CopyDir(strFileFrom, strPathTo, bEmptyDir, bOverwrites, depth - 1);
                    }
                    else
                    {
                        CopyDir(strFileFrom + _T("\\") + strFindName, strPathTo, bEmptyDir, bOverwrites, depth - 1);
                    }
                }

            } while (::FindNextFile(hFindHandle, &findData));

            ::FindClose(hFindHandle);

        } while (false);

        return true;
    }

    bool Delete(const _tstring& strPath)
    {
        if (IsFile(strPath))
        {
            return DeleteArchive(strPath);
        }

        if (IsDirectory(strPath))
        {
            return DeleteDir(strPath);
        }

        return false;
    }

    bool DeleteArchive(const _tstring& strPath)
    {
        if (strPath.empty())
        {
            return false;
        }

        return ::DeleteFile(strPath.c_str());
    }

    bool DeleteDir(const _tstring& strResult, bool bSubOnly/* = false*/)
    {
        WIN32_FIND_DATA findData = { 0 };
        HANDLE hFindHandle = INVALID_HANDLE_VALUE;

        if (strResult.empty())
        {
            return false;
        }

        hFindHandle = FindFirstFile((strResult + _T("\\*")).c_str(), &findData);
        if (INVALID_HANDLE_VALUE == hFindHandle)
        {
            return false;
        }

        do
        {
            _tstring strFilePath = strResult + _T("\\") + findData.cFileName;

            //上一级目录与当前目录跳过
            if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
            {
                continue;
            }

            if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //删除目录
            {
                DeleteDir(strFilePath, false);
                continue;
            }
            else    //删除文件
            {
                ::DeleteFile(strFilePath.c_str());
            }

        } while (::FindNextFile(hFindHandle, &findData));
        ::FindClose(hFindHandle);

        if (bSubOnly)
        {
            return true;
        }

        return ::RemoveDirectory(strResult.c_str());
    }

    bool CreateDir(const _tstring& strPath)
    {
        _tstring strDriver;              //驱动器号, 如 D:
        _tstring strSubPath = strPath;   //路径, 如 Test\1\2\3

        if (strPath.empty())
        {
            return false;
        }

        //获取盘符
        do
        {
            size_t nFindIndex = strPath.find_first_of(':');  //检查是否有驱动器号
            if (nFindIndex == _tstring::npos)
            {
                break;
            }

            strDriver = strPath.substr(0, nFindIndex + 1); //得到驱动器号, 如 D:
            nFindIndex = strPath.find(_T("\\"), nFindIndex);
            if (nFindIndex == _tstring::npos)
            {
                break;
            }

            strSubPath = strPath.substr(nFindIndex + 1); //得到路径, 如 Test\1\2\3
        } while (false);

        _tstring strDestDir;
        size_t nFindBegin = 0;
        size_t nFindIndex = 0;
        do
        {
            nFindIndex = strSubPath.find(_T("\\"), nFindBegin);
            if (nFindIndex != _tstring::npos)
            {
                strDestDir = strSubPath.substr(0, nFindIndex);
                nFindBegin = nFindIndex + 1;
            }
            else
            {
                strDestDir = strSubPath;
            }

            if (!strDriver.empty())
            {
                strDestDir = strDriver + _T("\\") + strDestDir;
            }

            if (!::CreateDirectory(strDestDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != ::GetLastError())
            {
                return false;
            }

        } while (nFindIndex != _tstring::npos);

        return true;
    }

    int SHCopy(const _tstring& strSrc, const _tstring& strDest)
    {
        _tstring strFrom = GetAbsolutePath(strSrc) + _T('\0');
        _tstring strTo = GetAbsolutePath(strDest) + _T('\0');

        SHFILEOPSTRUCT sfos = { 0 };
        sfos.wFunc = FO_COPY;
        sfos.pFrom = strFrom.c_str();   //注意 此字符串必须以双 null 结尾
        sfos.pTo = strTo.c_str();       //注意 此字符串必须以双 null 结尾
        sfos.fFlags = FOF_NO_UI | FOF_FILESONLY;

        return SHFileOperation(&sfos);
    }

    int SHMove(const _tstring& strSrc, const _tstring& strDest)
    {
        _tstring strFrom = GetAbsolutePath(strSrc) + _T('\0');
        _tstring strTo = GetAbsolutePath(strDest) + _T('\0');

        SHFILEOPSTRUCT sfos = { 0 };
        sfos.wFunc = FO_MOVE;
        sfos.pFrom = strFrom.c_str();   //注意 此字符串必须以双 null 结尾
        sfos.pTo = strTo.c_str();       //注意 此字符串必须以双 null 结尾
        sfos.fFlags = FOF_NO_UI;

        return SHFileOperation(&sfos);
    }

    int SHRename(const _tstring& strSrc, const _tstring& strDest)
    {
        _tstring strFrom = GetAbsolutePath(strSrc) + _T('\0');
        _tstring strTo = GetAbsolutePath(strDest) + _T('\0');

        SHFILEOPSTRUCT sfos = { 0 };
        sfos.wFunc = FO_RENAME;
        sfos.pFrom = strFrom.c_str();   //注意 此字符串必须以双 null 结尾
        sfos.pTo = strTo.c_str();       //注意 此字符串必须以双 null 结尾
        sfos.fFlags = FOF_NO_UI;

        return SHFileOperation(&sfos);
    }

    int SHDelete(const _tstring& strSrc)
    {
        _tstring strFrom = GetAbsolutePath(strSrc) + _T('\0');

        SHFILEOPSTRUCT sfos = { 0 };
        sfos.wFunc = FO_DELETE;
        sfos.pFrom = strFrom.c_str();   //注意 此字符串必须以双 null 结尾
        sfos.fFlags = FOF_NO_UI;

        return SHFileOperation(&sfos);
    }

    _tstring GetExpandEnvStrings(const _tstring& strPath)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::ExpandEnvironmentStrings(strPath.c_str(), szBuf, _countof(szBuf));
        return szBuf;
    }

    _tstring GetUnExpandEnvStrings(const _tstring& strPath)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::PathUnExpandEnvStrings(strPath.c_str(), szBuf, _countof(szBuf));
        return szBuf;
    }

    std::vector<_tstring> GetPathList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::vector<_tstring> fileList;
        _tstring strSrcDir = GetAbsolutePath(strDir);
        _GetPathList(fileList, strSrcDir, extList, depth, dwExclude, dwContain);
        return fileList;
    }

    std::vector<_tstring> GetCurrentPathList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::vector<_tstring> fileList;
        _tstring strSrcDir = GetCurrentAbsolutePath(strDir);
        _GetPathList(fileList, strSrcDir, extList, depth, dwExclude, dwContain);
        return fileList;
    }

    std::vector<FILEINFO> GetFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::vector<FILEINFO> fileList;
        _tstring strSrcDir = GetAbsolutePath(strDir);
        _GetFileInfoList(fileList, strSrcDir, extList, depth, dwExclude, dwContain);
        return fileList;
    }

    std::vector<FILEINFO> GetCurrentFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::vector<FILEINFO> fileList;
        _tstring strSrcDir = GetCurrentAbsolutePath(strDir);
        _GetFileInfoList(fileList, strSrcDir, extList, depth, dwExclude, dwContain);
        return fileList;
    }

    std::map<_tstring, FILEINFO> GetPathAndFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::map<_tstring, FILEINFO> fileList;
        _tstring strSrcDir = GetAbsolutePath(strDir);
        _GetPathAndPathInfoList(fileList, strSrcDir, extList, depth, dwExclude, dwContain);
        return fileList;
    }

    std::map<_tstring, FILEINFO> GetCurrentPathAndFileInfoList(
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::map<_tstring, FILEINFO> fileList;
        _tstring strSrcDir = GetCurrentAbsolutePath(strDir);
        _GetPathAndPathInfoList(fileList, strSrcDir, extList, depth, dwExclude, dwContain);
        return fileList;
    }

    std::vector<_tstring> SearchFiles(
        const _tstring& strFile,
        const _tstring& strSrcName,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        std::vector<_tstring> fileList;
        _tstring strSrcDir = GetAbsolutePath(strFile);
        _tstring strName = strSrcName;

        if (strName.empty())
        {
            strName = _T("*");
        }

        if (GetFileDir(strName).empty())
        {
            _SearchFiles(fileList, strSrcDir, strName, depth, dwExclude, dwContain);
        }
        return fileList;
    }

    void _SearchFiles(
        std::vector<_tstring>& fileList,
        const _tstring& strSrcDir,
        const _tstring& strSrcName,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        //到达深度限制返回
        if (depth < 0)
        {
            return;
        }

        WIN32_FIND_DATA findData = { 0 };
        HANDLE hFindHandle = INVALID_HANDLE_VALUE;

        if (!IsDirectory(strSrcDir))
        {
            return;
        }

        //先搜索符合规则的文件
        do
        {
            _tstring strFindFile = strSrcDir + _T("\\") + strSrcName;
            hFindHandle = FindFirstFile(strFindFile.c_str(), &findData);
            if (INVALID_HANDLE_VALUE == hFindHandle)
            {
                break;
            }

            do
            {
                bool bExclude = false;
                bool bContain = false;

                //上一级目录与当前目录跳过
                if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
                {
                    continue;
                }

                // 检查排除属性
                if (0 != dwExclude && (0 != (findData.dwFileAttributes & dwExclude)))
                {
                    bExclude = true;
                }

                // 检查包含属性
                if (0 == dwContain)
                {
                    bContain = true;
                }
                else if (dwContain == (findData.dwFileAttributes & dwContain))
                {
                    bContain = true;
                }

                // 属性检查
                if (!bExclude && bContain && (0 == (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
                {
                    fileList.emplace_back(strSrcDir + _T("\\") + findData.cFileName);
                }

            } while (::FindNextFile(hFindHandle, &findData));

            ::FindClose(hFindHandle);

        } while (false);

        //后搜索文件夹
        do
        {
            _tstring strFindFile = strSrcDir + _T("\\*");
            hFindHandle = FindFirstFile(strFindFile.c_str(), &findData);
            if (INVALID_HANDLE_VALUE == hFindHandle)
            {
                break;
            }

            do
            {
                bool bExclude = false;
                bool bContain = false;

                //上一级目录与当前目录跳过
                if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
                {
                    continue;
                }

                if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                {
                    _SearchFiles(fileList, strSrcDir + _T("\\") + findData.cFileName, strSrcName, depth - 1, dwExclude, dwContain);
                }

            } while (::FindNextFile(hFindHandle, &findData));

            ::FindClose(hFindHandle);

        } while (false);
    }

    void _GetPathListEx(
        const _tstring& dir,
        std::function<bool(const _tstring strPath, const WIN32_FIND_DATA& findData)> cb,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        //到达深度限制返回
        if (depth < 0)
        {
            return;
        }

        WIN32_FIND_DATA findData = { 0 };
        HANDLE hFindHandle = INVALID_HANDLE_VALUE;
        hFindHandle = ::FindFirstFile((dir + _T("\\*")).c_str(), &findData);
        if (INVALID_HANDLE_VALUE == hFindHandle)
        {
            return;
        }

        do
        {
            // 上一级目录与当前目录跳过
            if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
            {
                continue;
            }

            bool bAbort = false;
            bool bExclude = false;
            bool bContain = false;

            // 检查排除属性
            if (0 != dwExclude && (0 != (findData.dwFileAttributes & dwExclude)))
            {
                bExclude = true;
            }

            // 检查包含属性
            if (0 == dwContain)
            {
                bContain = true;
            }
            else if (dwContain == (findData.dwFileAttributes & dwContain))
            {
                bContain = true;
            }

            // 路径
            _tstring strPath = dir + _T("\\") + findData.cFileName;

            if (!bExclude && bContain && cb)
            {
                if (extList.empty())
                {
                    bAbort = !cb(strPath, findData);
                    if (bAbort)
                    {
                        break;
                    }
                }
                else
                {
                    // 获取扩展名
                    _tstring strExtName = findData.cFileName;
                    size_t nIndex = strExtName.find_last_of(_T('.'));
                    if (nIndex != _tstring::npos)
                    {
                        strExtName = strExtName.substr(nIndex + 1);
                    }
                    else
                    {
                        strExtName = _T("");
                    }

                    // 进行扩展名过滤
                    for (const auto& item : extList)
                    {
                        if (0 == _tcsicmp(item.c_str(), strExtName.c_str()))
                        {
                            bAbort = !cb(strPath, findData);
                            if (bAbort)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            if (bAbort)
            {
                break;
            }

            // 目录
            if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
            {
                _GetPathListEx(strPath, cb, extList, depth - 1);
            }

        } while (::FindNextFile(hFindHandle, &findData));

        ::FindClose(hFindHandle);
    }

    void _GetPathList(
        std::vector<_tstring>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth /*  = MAX_PATH */,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        _GetPathListEx(strDir, [&fileList, &extList, dwExclude, dwContain](const _tstring strPath, const WIN32_FIND_DATA& findData) -> bool {
            fileList.push_back(strPath);
            return true;
            }, {}, depth, dwExclude, dwContain
        );
    }

    void _GetFileInfoList(
        std::vector<FILEINFO>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList/* = {}*/,
        int32_t depth/* = MAX_PATH*/,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        _GetPathListEx(strDir, [&fileList, &extList, dwExclude, dwContain](const _tstring strPath, const WIN32_FIND_DATA& findData) -> bool {
            FILEINFO info;
            info.m_filePath = strPath;
            info.m_fileSize = (unsigned long long)findData.nFileSizeHigh << 32 | findData.nFileSizeLow;
            info.m_ftCreationTime = *(size_t*)&findData.ftCreationTime;
            info.m_ftLastAccessTime = *(size_t*)&findData.ftLastAccessTime;
            info.m_ftLastWriteTime = *(size_t*)&findData.ftLastWriteTime;
            info.m_fileAttributes = findData.dwFileAttributes;

            info.m_ftCreationTime = (info.m_ftCreationTime - 116444736000000000) / 10000000;
            info.m_ftLastAccessTime = (info.m_ftLastAccessTime - 116444736000000000) / 10000000;
            info.m_ftLastWriteTime = (info.m_ftLastWriteTime - 116444736000000000) / 10000000;

            fileList.push_back(info);

            return true;
            }, {}, depth, dwExclude, dwContain
        );
    }

    void _GetPathAndPathInfoList(
        std::map<_tstring, FILEINFO>& fileList,
        const _tstring& dir,
        const std::vector<_tstring>& extList /* = {} */,
        int32_t depth /*  = MAX_PATH */,
        DWORD dwExclude/* = 0*/,
        DWORD dwContain/* = 0*/
    )
    {
        _GetPathListEx(dir, [&fileList, &extList, dwExclude, dwContain](const _tstring strPath, const WIN32_FIND_DATA& findData) -> bool {
            FILEINFO info;
            info.m_filePath = strPath;
            info.m_fileSize = (unsigned long long)findData.nFileSizeHigh << 32 | findData.nFileSizeLow;
            info.m_ftCreationTime = *(size_t*)&findData.ftCreationTime;
            info.m_ftLastAccessTime = *(size_t*)&findData.ftLastAccessTime;
            info.m_ftLastWriteTime = *(size_t*)&findData.ftLastWriteTime;
            info.m_fileAttributes = findData.dwFileAttributes;

            info.m_ftCreationTime = (info.m_ftCreationTime - 116444736000000000) / 10000000;
            info.m_ftLastAccessTime = (info.m_ftLastAccessTime - 116444736000000000) / 10000000;
            info.m_ftLastWriteTime = (info.m_ftLastWriteTime - 116444736000000000) / 10000000;

            fileList.emplace(std::make_pair(strPath, info));

            return true;
            }, {}, depth, dwExclude, dwContain
        );
    }

    ULONGLONG GetDiskFreeSize(const _tstring& strDir)
    {
        ULARGE_INTEGER ullFreeBytesAvailableToCaller = { 0 };
        ULARGE_INTEGER ullTotalNumberOfBytes = { 0 };
        ULARGE_INTEGER ullTotalNumberOfFreeBytes = { 0 };

        ::GetDiskFreeSpaceEx(strDir.c_str(),
            &ullFreeBytesAvailableToCaller,
            &ullTotalNumberOfBytes,
            &ullTotalNumberOfFreeBytes
        );

        return ullTotalNumberOfFreeBytes.QuadPart;
    }

    ULONGLONG GetDiskTotalSize(const _tstring& strDir)
    {
        ULARGE_INTEGER ullFreeBytesAvailableToCaller = { 0 };
        ULARGE_INTEGER ullTotalNumberOfBytes = { 0 };
        ULARGE_INTEGER ullTotalNumberOfFreeBytes = { 0 };

        ::GetDiskFreeSpaceEx(strDir.c_str(),
            &ullFreeBytesAvailableToCaller,
            &ullTotalNumberOfBytes,
            &ullTotalNumberOfFreeBytes
        );

        return ullTotalNumberOfBytes.QuadPart;
    }

    _tstring GetKnownFolder(_In_ REFKNOWNFOLDERID rfid)
    {
        _tstring strFolder;
        LPWSTR pstr = NULL;
        HRESULT hr = S_OK;
        hr = SHGetKnownFolderPath(rfid, KF_FLAG_DEFAULT, NULL, &pstr);
        if (NULL != pstr)
        {
#ifdef _UNICODE
            strFolder = pstr;
#else
            CHAR szBuf[MAX_PATH] = { 0 };
            int nConverted = ::WideCharToMultiByte(CP_ACP, 0, pstr, -1, szBuf, _countof(szBuf), NULL, NULL);
            if (0 != nConverted)
            {
                strFolder = szBuf;
            }
#endif

            CoTaskMemFree(pstr);
        }

        return strFolder;
    }

    _tstring GetNetworkFolder() { return  GetKnownFolder(FOLDERID_NetworkFolder); }
    _tstring GetComputerFolder() { return  GetKnownFolder(FOLDERID_ComputerFolder); }
    _tstring GetInternetFolder() { return  GetKnownFolder(FOLDERID_InternetFolder); }
    _tstring GetControlPanelFolder() { return  GetKnownFolder(FOLDERID_ControlPanelFolder); }
    _tstring GetPrintersFolder() { return  GetKnownFolder(FOLDERID_PrintersFolder); }
    _tstring GetSyncManagerFolder() { return  GetKnownFolder(FOLDERID_SyncManagerFolder); }
    _tstring GetSyncSetupFolder() { return  GetKnownFolder(FOLDERID_SyncSetupFolder); }
    _tstring GetConflictFolder() { return  GetKnownFolder(FOLDERID_ConflictFolder); }
    _tstring GetSyncResultsFolder() { return  GetKnownFolder(FOLDERID_SyncResultsFolder); }
    _tstring GetRecycleBinFolder() { return  GetKnownFolder(FOLDERID_RecycleBinFolder); }
    _tstring GetConnectionsFolder() { return  GetKnownFolder(FOLDERID_ConnectionsFolder); }
    _tstring GetFonts() { return  GetKnownFolder(FOLDERID_Fonts); }
    _tstring GetDesktop() { return  GetKnownFolder(FOLDERID_Desktop); }
    _tstring GetStartup() { return  GetKnownFolder(FOLDERID_Startup); }
    _tstring GetPrograms() { return  GetKnownFolder(FOLDERID_Programs); }
    _tstring GetStartMenu() { return  GetKnownFolder(FOLDERID_StartMenu); }
    _tstring GetRecent() { return  GetKnownFolder(FOLDERID_Recent); }
    _tstring GetSendTo() { return  GetKnownFolder(FOLDERID_SendTo); }
    _tstring GetDocuments() { return  GetKnownFolder(FOLDERID_Documents); }
    _tstring GetFavorites() { return  GetKnownFolder(FOLDERID_Favorites); }
    _tstring GetNetHood() { return  GetKnownFolder(FOLDERID_NetHood); }
    _tstring GetPrintHood() { return  GetKnownFolder(FOLDERID_PrintHood); }
    _tstring GetTemplates() { return  GetKnownFolder(FOLDERID_Templates); }
    _tstring GetCommonStartup() { return  GetKnownFolder(FOLDERID_CommonStartup); }
    _tstring GetCommonPrograms() { return  GetKnownFolder(FOLDERID_CommonPrograms); }
    _tstring GetCommonStartMenu() { return  GetKnownFolder(FOLDERID_CommonStartMenu); }
    _tstring GetPublicDesktop() { return  GetKnownFolder(FOLDERID_PublicDesktop); }
    _tstring GetProgramData() { return  GetKnownFolder(FOLDERID_ProgramData); }
    _tstring GetCommonTemplates() { return  GetKnownFolder(FOLDERID_CommonTemplates); }
    _tstring GetPublicDocuments() { return  GetKnownFolder(FOLDERID_PublicDocuments); }
    _tstring GetRoamingAppData() { return  GetKnownFolder(FOLDERID_RoamingAppData); }
    _tstring GetLocalAppData() { return  GetKnownFolder(FOLDERID_LocalAppData); }
    _tstring GetLocalAppDataLow() { return  GetKnownFolder(FOLDERID_LocalAppDataLow); }
    _tstring GetInternetCache() { return  GetKnownFolder(FOLDERID_InternetCache); }
    _tstring GetCookies() { return  GetKnownFolder(FOLDERID_Cookies); }
    _tstring GetHistory() { return  GetKnownFolder(FOLDERID_History); }
    _tstring GetSystem() { return  GetKnownFolder(FOLDERID_System); }
    _tstring GetSystemX86() { return  GetKnownFolder(FOLDERID_SystemX86); }
    _tstring GetWindows() { return  GetKnownFolder(FOLDERID_Windows); }
    _tstring GetProfile() { return  GetKnownFolder(FOLDERID_Profile); }
    _tstring GetPictures() { return  GetKnownFolder(FOLDERID_Pictures); }
    _tstring GetProgramFilesX86() { return  GetKnownFolder(FOLDERID_ProgramFilesX86); }
    _tstring GetProgramFilesCommonX86() { return  GetKnownFolder(FOLDERID_ProgramFilesCommonX86); }
    _tstring GetProgramFilesX64() { return  GetKnownFolder(FOLDERID_ProgramFilesX64); }
    _tstring GetProgramFilesCommonX64() { return  GetKnownFolder(FOLDERID_ProgramFilesCommonX64); }
    _tstring GetProgramFiles() { return  GetKnownFolder(FOLDERID_ProgramFiles); }
    _tstring GetProgramFilesCommon() { return  GetKnownFolder(FOLDERID_ProgramFilesCommon); }
    _tstring GetUserProgramFiles() { return  GetKnownFolder(FOLDERID_UserProgramFiles); }
    _tstring GetUserProgramFilesCommon() { return  GetKnownFolder(FOLDERID_UserProgramFilesCommon); }
    _tstring GetAdminTools() { return  GetKnownFolder(FOLDERID_AdminTools); }
    _tstring GetCommonAdminTools() { return  GetKnownFolder(FOLDERID_CommonAdminTools); }
    _tstring GetMusic() { return  GetKnownFolder(FOLDERID_Music); }
    _tstring GetVideos() { return  GetKnownFolder(FOLDERID_Videos); }
    _tstring GetRingtones() { return  GetKnownFolder(FOLDERID_Ringtones); }
    _tstring GetPublicPictures() { return  GetKnownFolder(FOLDERID_PublicPictures); }
    _tstring GetPublicMusic() { return  GetKnownFolder(FOLDERID_PublicMusic); }
    _tstring GetPublicVideos() { return  GetKnownFolder(FOLDERID_PublicVideos); }
    _tstring GetPublicRingtones() { return  GetKnownFolder(FOLDERID_PublicRingtones); }
    _tstring GetResourceDir() { return  GetKnownFolder(FOLDERID_ResourceDir); }
    _tstring GetLocalizedResourcesDir() { return  GetKnownFolder(FOLDERID_LocalizedResourcesDir); }
    _tstring GetCommonOEMLinks() { return  GetKnownFolder(FOLDERID_CommonOEMLinks); }
    _tstring GetCDBurning() { return  GetKnownFolder(FOLDERID_CDBurning); }
    _tstring GetUserProfiles() { return  GetKnownFolder(FOLDERID_UserProfiles); }
    _tstring GetPlaylists() { return  GetKnownFolder(FOLDERID_Playlists); }
    _tstring GetSamplePlaylists() { return  GetKnownFolder(FOLDERID_SamplePlaylists); }
    _tstring GetSampleMusic() { return  GetKnownFolder(FOLDERID_SampleMusic); }
    _tstring GetSamplePictures() { return  GetKnownFolder(FOLDERID_SamplePictures); }
    _tstring GetSampleVideos() { return  GetKnownFolder(FOLDERID_SampleVideos); }
    _tstring GetPhotoAlbums() { return  GetKnownFolder(FOLDERID_PhotoAlbums); }
    _tstring GetPublic() { return  GetKnownFolder(FOLDERID_Public); }
    _tstring GetChangeRemovePrograms() { return  GetKnownFolder(FOLDERID_ChangeRemovePrograms); }
    _tstring GetAppUpdates() { return  GetKnownFolder(FOLDERID_AppUpdates); }
    _tstring GetAddNewPrograms() { return  GetKnownFolder(FOLDERID_AddNewPrograms); }
    _tstring GetDownloads() { return  GetKnownFolder(FOLDERID_Downloads); }
    _tstring GetPublicDownloads() { return  GetKnownFolder(FOLDERID_PublicDownloads); }
    _tstring GetSavedSearches() { return  GetKnownFolder(FOLDERID_SavedSearches); }
    _tstring GetQuickLaunch() { return  GetKnownFolder(FOLDERID_QuickLaunch); }
    _tstring GetContacts() { return  GetKnownFolder(FOLDERID_Contacts); }
    _tstring GetSidebarParts() { return  GetKnownFolder(FOLDERID_SidebarParts); }
    _tstring GetSidebarDefaultParts() { return  GetKnownFolder(FOLDERID_SidebarDefaultParts); }
    _tstring GetPublicGameTasks() { return  GetKnownFolder(FOLDERID_PublicGameTasks); }
    _tstring GetGameTasks() { return  GetKnownFolder(FOLDERID_GameTasks); }
    _tstring GetSavedGames() { return  GetKnownFolder(FOLDERID_SavedGames); }
    _tstring GetGames() { return  GetKnownFolder(FOLDERID_Games); }
    _tstring GetSEARCH_MAPI() { return  GetKnownFolder(FOLDERID_SEARCH_MAPI); }
    _tstring GetSEARCH_CSC() { return  GetKnownFolder(FOLDERID_SEARCH_CSC); }
    _tstring GetLinks() { return  GetKnownFolder(FOLDERID_Links); }
    _tstring GetUsersFiles() { return  GetKnownFolder(FOLDERID_UsersFiles); }
    _tstring GetUsersLibraries() { return  GetKnownFolder(FOLDERID_UsersLibraries); }
    _tstring GetSearchHome() { return  GetKnownFolder(FOLDERID_SearchHome); }
    _tstring GetOriginalImages() { return  GetKnownFolder(FOLDERID_OriginalImages); }
    _tstring GetDocumentsLibrary() { return  GetKnownFolder(FOLDERID_DocumentsLibrary); }
    _tstring GetMusicLibrary() { return  GetKnownFolder(FOLDERID_MusicLibrary); }
    _tstring GetPicturesLibrary() { return  GetKnownFolder(FOLDERID_PicturesLibrary); }
    _tstring GetVideosLibrary() { return  GetKnownFolder(FOLDERID_VideosLibrary); }
    _tstring GetRecordedTVLibrary() { return  GetKnownFolder(FOLDERID_RecordedTVLibrary); }
    _tstring GetHomeGroup() { return  GetKnownFolder(FOLDERID_HomeGroup); }
    _tstring GetHomeGroupCurrentUser() { return  GetKnownFolder(FOLDERID_HomeGroupCurrentUser); }
    _tstring GetDeviceMetadataStore() { return  GetKnownFolder(FOLDERID_DeviceMetadataStore); }
    _tstring GetLibraries() { return  GetKnownFolder(FOLDERID_Libraries); }
    _tstring GetPublicLibraries() { return  GetKnownFolder(FOLDERID_PublicLibraries); }
    _tstring GetUserPinned() { return  GetKnownFolder(FOLDERID_UserPinned); }
    _tstring GetImplicitAppShortcuts() { return  GetKnownFolder(FOLDERID_ImplicitAppShortcuts); }
    _tstring GetAccountPictures() { return  GetKnownFolder(FOLDERID_AccountPictures); }
    _tstring GetPublicUserTiles() { return  GetKnownFolder(FOLDERID_PublicUserTiles); }
    _tstring GetAppsFolder() { return  GetKnownFolder(FOLDERID_AppsFolder); }
    _tstring GetStartMenuAllPrograms() { return  GetKnownFolder(FOLDERID_StartMenuAllPrograms); }
    _tstring GetCommonStartMenuPlaces() { return  GetKnownFolder(FOLDERID_CommonStartMenuPlaces); }
    _tstring GetApplicationShortcuts() { return  GetKnownFolder(FOLDERID_ApplicationShortcuts); }
    _tstring GetRoamingTiles() { return  GetKnownFolder(FOLDERID_RoamingTiles); }
    _tstring GetRoamedTileImages() { return  GetKnownFolder(FOLDERID_RoamedTileImages); }
    _tstring GetScreenshots() { return  GetKnownFolder(FOLDERID_Screenshots); }
    _tstring GetCameraRoll() { return  GetKnownFolder(FOLDERID_CameraRoll); }
    _tstring GetSkyDrive() { return  GetKnownFolder(FOLDERID_SkyDrive); }
    _tstring GetOneDrive() { return  GetKnownFolder(FOLDERID_OneDrive); }
    _tstring GetSkyDriveDocuments() { return  GetKnownFolder(FOLDERID_SkyDriveDocuments); }
    _tstring GetSkyDrivePictures() { return  GetKnownFolder(FOLDERID_SkyDrivePictures); }
    _tstring GetSkyDriveMusic() { return  GetKnownFolder(FOLDERID_SkyDriveMusic); }
    _tstring GetSkyDriveCameraRoll() { return  GetKnownFolder(FOLDERID_SkyDriveCameraRoll); }
    _tstring GetSearchHistory() { return  GetKnownFolder(FOLDERID_SearchHistory); }
    _tstring GetSearchTemplates() { return  GetKnownFolder(FOLDERID_SearchTemplates); }
    _tstring GetCameraRollLibrary() { return  GetKnownFolder(FOLDERID_CameraRollLibrary); }
    _tstring GetSavedPictures() { return  GetKnownFolder(FOLDERID_SavedPictures); }
    _tstring GetSavedPicturesLibrary() { return  GetKnownFolder(FOLDERID_SavedPicturesLibrary); }
    _tstring GetRetailDemo() { return  GetKnownFolder(FOLDERID_RetailDemo); }
    _tstring GetDevice() { return  GetKnownFolder(FOLDERID_Device); }
    _tstring GetDevelopmentFiles() { return  GetKnownFolder(FOLDERID_DevelopmentFiles); }
    _tstring GetObjects3D() { return  GetKnownFolder(FOLDERID_Objects3D); }
    _tstring GetAppCaptures() { return  GetKnownFolder(FOLDERID_AppCaptures); }
    _tstring GetLocalDocuments() { return  GetKnownFolder(FOLDERID_LocalDocuments); }
    _tstring GetLocalPictures() { return  GetKnownFolder(FOLDERID_LocalPictures); }
    _tstring GetLocalVideos() { return  GetKnownFolder(FOLDERID_LocalVideos); }
    _tstring GetLocalMusic() { return  GetKnownFolder(FOLDERID_LocalMusic); }
    _tstring GetLocalDownloads() { return  GetKnownFolder(FOLDERID_LocalDownloads); }
    _tstring GetRecordedCalls() { return  GetKnownFolder(FOLDERID_RecordedCalls); }
    _tstring GetAllAppMods() { return  GetKnownFolder(FOLDERID_AllAppMods); }
    _tstring GetCurrentAppMods() { return  GetKnownFolder(FOLDERID_CurrentAppMods); }
    _tstring GetAppDataDesktop() { return  GetKnownFolder(FOLDERID_AppDataDesktop); }
    _tstring GetAppDataDocuments() { return  GetKnownFolder(FOLDERID_AppDataDocuments); }
    _tstring GetAppDataFavorites() { return  GetKnownFolder(FOLDERID_AppDataFavorites); }
    _tstring GetAppDataProgramData() { return  GetKnownFolder(FOLDERID_AppDataProgramData); }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值