【发布时间】:2019-04-23 19:27:46
【问题描述】:
短版
是否有与用户的整个个人资料相对应的 IShellItem?
或者给定所有已知的 KNOWNFOLDER 常量:
- 有没有办法知道 KNOWNFOLDER 常量是否是用户配置文件的一部分
- 有没有办法枚举尚未发明的 KNOWNFOLDER 常量,所以我不会错过任何?
加长版
如果我想备份用户的整个个人资料,我当然会从
SHGetFolderPath(CSIDL_PROFILE): "C:\Users\Ian"
这很明显。该文件夹通常会包含:
C:\Users\Ian
╰── AppData
├── Local
├── LocalLow
╰── Roaming
其中一些其他文件夹已经作为它们自己的 CSIDL 常量存在
C:\Users\Ian CSIDL_Profile
╰── AppData
├── Local CSIDL_Local_AppData
├── LocalLow
╰── Roaming CSIDL_AppData
有时还有其他配置文件文件夹出现在 Profile 文件夹中:
C:\Users\Ian CSIDL_Profile
├── Desktop CSIDL_DesktopDirectoy
├── Documents CSIDL_Personal
├── Pictures CSIDL_MyPictures
├── Music CSIDL_MyMusic
├── Video CSIDL_MyVideo
├── Favorites CSIDL_Favorites
╰── AppData
├── Local CSIDL_Local_AppData
├── LocalLow
╰── Roaming CSIDL_AppData
但这些文件夹不必在 %USERPROFILE% 下
Windows 允许用户配置某些特殊文件夹以移动到自定义位置:
这意味着某些文件夹实际上可以存在于“Profile”文件夹之外:
C:\Users\Ian CSIDL_Profile
╰── AppData
├── Local CSIDL_Local_AppData
╰── LocalLow
D:\Users\Ian
├── Desktop CSIDL_DesktopDirectoy
├── Documents CSIDL_Personal
├── Pictures CSIDL_MyPictures
├── Music CSIDL_MyMusic
├── Video CSIDL_MyVideo
├── Favorites CSIDL_Favorites
╰── AppData
╰── Roaming CSIDL_AppData
还有一大堆 CSIDL 值,我不知道它们是否可以通过 UI、组策略或以其他方式移动到其他位置:
C:\Users\Ian CSIDL_Profile
╰── AppData
├── Local CSIDL_Local_AppData
│ ├── Microsoft\Windows\History CSIDL_HISTORY
│ ├── Microsoft\Windows\Temporary Internet Files CSIDL_INTERNET_CACHE
│ ╰── Microsoft\Windows\Burn\Burn1 CSIDL_CDBURN_AREA
╰── LocalLow
D:\Users\Ian
├── Desktop CSIDL_DesktopDirectoy
├── Documents CSIDL_Personal
├── Pictures CSIDL_MyPictures
├── Music CSIDL_MyMusic
├── Video CSIDL_MyVideo
├── Favorites CSIDL_Favorites
╰── AppData
╰── Roaming CSIDL_AppData
╰── Microsoft
╰── Windows
├── Recent CSIDL_RECENT
├── Send To CSIDL_SENDTO
├── Start Menu CSIDL_STARTMENU
│ ╰── Programs CSIDL_PROGRAMS
│ ├── Startup CSIDL_STARTUP
│ ├── Startup CSIDL_ALTSTARTUP
│ ╰── Administrative Tools CSIDL_ADMINTOOLS
├── Templates CSIDL_TEMPLATES
╰── Cookies CSIDL_TEMPLATES
我不想错过文件夹
使用所有这些 CSIDL 值,我可能会错过一些构成用户配置文件的文件夹。在我理想的幻想世界中,会有一个 IShellItem 对应于用户个人资料中的所有内容几乎。
如果你查看这台电脑文件夹(CSIDL_DRIVES)(formerly称为My Computer),它是一个虚拟的包含以下内容的 shell 文件夹:
This PC
├── 3D Objects
├── Desktop
├── Documents
├── Downloads
├── Music
├── Pictures
╰── Videos
这太棒了;它是一个虚拟文件夹,其中包含构成用户配置文件的文件夹(无论这些文件夹实际位于何处)。
不幸的是,它有两个缺点:
- 它丢失了一些配置文件文件夹(例如 CSIDL_Favorites)
-
然后它继续包括所有我的电脑(nee 这台电脑)
This PC ├── 3D Objects ├── Desktop ├── Documents ├── Downloads ├── Music ├── Pictures ├── Videos ├── OS (C:) ├── Develop (D:) ├── DVD RW Drive (E:) ├── BD ROM Drive (F:) ╰── Local Disk (X:)
“所以只需备份代表每个用户文件夹的所有 CSIDL”
我想我可以简单地查看每个 CSIDL,剔除作为另一个 IShellItem 子级的任何 IShellItem(待办事项:弄清楚如何做到这一点),然后然后只备份那些:
CSIDL_PROFILE C:\Users\ian
CSIDL_LOCAL_APPDATA C:\Users\ian\AppData\Local
CSIDL_APPDATA C:\Users\ian\AppData\Roaming
CSIDL_NETHOOD C:\Users\ian\AppData\Roaming\Microsoft\Windows\Network Shortcuts
CSIDL_PRINTHOOD C:\Users\ian\AppData\Roaming\Microsoft\Windows\Printer Shortcuts
CSIDL_DESKTOP D:\Users\ian\Desktop
CSIDL_DESKTOPDIRECTORY D:\Users\ian\Desktop
CSIDL_PERSONAL D:\Users\ian\Documents
CSIDL_MYPICTURES D:\Users\ian\Pictures
CSIDL_MYMUSIC D:\Users\ian\Music
CSIDL_MYVIDEO D:\Users\ian\Videos
CSIDL_FAVORITES D:\Users\ian\Favorites
CSIDL_COMMON_FAVORITES D:\Users\ian\Favorites
CSIDL_RECENT d:\Users\ian\AppData\Roaming\Microsoft\Windows\Recent
CSIDL_SENDTO d:\Users\ian\AppData\Roaming\Microsoft\Windows\SendTo
CSIDL_STARTMENU d:\Users\ian\AppData\Roaming\Microsoft\Windows\Start Menu
CSIDL_PROGRAMS d:\Users\ian\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
CSIDL_STARTUP d:\Users\ian\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
CSIDL_ALTSTARTUP d:\Users\ian\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
CSIDL_ADMINTOOLS d:\Users\ian\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tools
CSIDL_TEMPLATES d:\Users\ian\AppData\Roaming\Microsoft\Windows\Templates
CSIDL_COOKIES d:\Users\ian\AppData\Roaming\Microsoft\Windows\Cookies
CSIDL_HISTORY d:\Users\ian\AppData\Local\Microsoft\Windows\History
CSIDL_INTERNET_CACHE d:\Users\ian\AppData\Local\Microsoft\Windows\Temporary Internet Files
CSIDL_CDBURN_AREA C:\Users\ian\AppData\Local\Microsoft\Windows\Burn\Burn1
问题在于 CSIDL 不完整(并且已弃用)。例如:
- 下载没有 CSIDL
- 3D 对象没有 CSIDL
好的,我会切换到现代的KNOWNFOLDERS。
这样我会得到:
- FOLDERID_AccountPictures
- FOLDERID_AppDataDesktop
- FOLDERID_AppDataFavorites
- FOLDERID_AppDataProgramData
- FOLDERID_Objects3D
- FOLDERID_OriginalImages
- 截图 34
- FOLDERID_Ringtones
除了 KnownFolders 没有帮助
我枚举所有已知 KNOWNFOLDER 常量的方案失败有两个原因。
我的应用程序编写后发明的任何常量都会丢失 - 丢失备份用户配置文件数据。对于备份应用程序来说,这不是一项好工作。
但更重要的是,我不知道哪些KNOWNFOLDERS是每个用户。例如:
-
FOLDERID_AppsFolder
- GUID:GUID {1e87508d-89c2-42f0-8a7e-645a0f50ca58}
- 显示名称:应用程序
- 文件夹类型:虚拟
- 默认路径:不适用 - 虚拟文件夹
应用程序是每个用户的吗?仅仅因为一个文件夹没有文件系统路径,并不意味着它不存在,或者我无法读取它,或者我无法枚举其文件,或者我无法备份它的内容
使用现代(即 Windows 95)Shell API 枚举文件和文件夹时,您可以很好地读取这些文件。
通过 USB 将手机插入 PC。您可以浏览文件,并使用 IShellItem api 枚举它们 - 即使它们没有文件系统路径。
总结
是否有一个 shell 虚拟文件夹对应于与用户个人资料相关的所有内容?
【问题讨论】:
-
用户配置文件还包括注册表......
-
@DavidHeffernan 大概在NTUSER.DAT举行
-
无论在哪里,都无法通过shell项访问
-
我的应用程序编写后发明的任何常量都会被遗漏 -- 这就是
IKnownFolderManager存在的原因。只是一个快速的想法:IKnownFolderManager::GetFolderIds()->IKnownFolderManager::GetFolder()->IKnownFolder::GetCategory()。如果类别等于KF_CATEGORY_PERUSER,则备份该文件夹。
标签: windows winapi windows-shell user-profile