是否存在与用户的整个个人资料相对应的 IShellItem ?
或给出所有已知的KNOWNFOLDER常数:
如果我想备份用户的整个个人资料,我当然会以
开头SHGetFolderPath(CSIDL_PROFILE): "C:\Users\Ian"
很明显。该文件夹通常将包含:
C:\Users\Ian
╰── AppData
├── Local
├── LocalLow
╰── Roaming
其中一些其他文件夹已经作为其自己的 CSIDL 常量
存在C:\Users\Ian CSIDL_Profile
╰── AppData
├── Local
├── LocalLow CSIDL_Local_AppData
╰── Roaming CSIDL_AppData
在个人资料文件夹中,有时还会出现 其他个人资料文件夹:
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
├── LocalLow CSIDL_Local_AppData
╰── Roaming CSIDL_AppData
Windows允许用户配置某些特殊文件夹以将其移动到自定义位置:
这意味着某些文件夹实际上可以存在于“个人资料” 文件夹之外:
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 ,它实际上与用户个人资料中的所有内容相对应。
以与查看此PC 文件夹(CSIDL_DRIVES
)(formerly known as My Computer)相同的方式,它是一个虚拟外壳包含以下内容的文件夹:
This PC
├── 3D Objects
├── Desktop
├── Documents
├── Downloads
├── Music
├── Pictures
╰── Videos
这太好了;这是一个虚拟文件夹,其中包含构成用户个人资料的文件夹(无论这些文件夹实际位于何处)。
不幸的是,它有两个缺点:
然后它继续包含所有我的电脑(请此PC )
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,剔除属于另一个 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不完整(不建议使用)。例如:
好的,我将改用现代的 KNOWNFOLDERS 。
这样我会得到:
我列举所有已知的 KNOWNFOLDER 常量的方案失败有两个原因。
编写我的应用程序后发明的任何常量都将丢失-缺少备份用户配置文件数据。对于备份应用程序来说不是一件好事。
但更重要的是,我不知道哪个已知用户是<用户>每个用户。例如:
每个用户应用吗?仅仅因为文件夹没有文件系统路径,并不意味着它不存在,或者我无法读取它,或者我无法枚举其文件,或者我无法备份其内容
使用现代(即Windows 95)Shell API枚举文件和文件夹时,您可以很好地读取这些文件。
通过USB将手机插入PC。您可以浏览文件,并使用 IShellItem API进行枚举-即使它们没有文件系统路径。
是否存在与用户个人资料相关的所有内容相对应的外壳虚拟文件夹?
答案 0 :(得分:3)
我认为不存在包含所有用户特殊文件夹的文件夹,最接近的文件夹是FOLDERID_UsersFiles
文件夹,但是我认为这与查看配置文件文件夹几乎相同。
已知文件夹可以由第三方应用程序创建,请参见IKnownFolderManager::RegisterFolder
:
特别由将自己的文件夹之一添加到已知文件夹系统的独立软件供应商(ISV)使用。
这意味着您将永远无法列出所有已发明或其他形式的清单。
我可以想到3种可能的解决方法,它们都涉及使用IKnownFolderManager
枚举已安装的已知文件夹。
IKnownFolder::GetCategory
并查找KF_CATEGORY_PERUSER
文件夹。
每个用户的文件夹是存储在每个用户的个人资料下并且只能由该用户访问的文件夹。
(我认为它们实际上是指默认情况下存储在用户个人资料中的文件夹。)
IKnownFolder::GetFolderDefinition
查找父文件夹,然后遍历父树以查看其是否以FOLDERID_Profile
结尾。
IKnownFolder::GetPath(KF_FLAG_DEFAULT_PATH,...)
并检查此路径是否在用户个人资料内。我认为没有理由选择这种方法。
在大多数情况下,前两种方法应给出相同的结果,但这确实取决于它们的注册方式。理论上,默认情况下,每个用户类别文件夹可以位于配置文件文件夹之外,而AFAIK则可以,而虚拟文件夹则可以将配置文件文件夹作为其父文件夹。使用Known Folders Browser或Known Folder Info之类的工具可能有助于可视化这些差异。
这并不涵盖大多数虚拟文件夹,例如FOLDERID_AppsFolder
,但我不确定是否应该备份虚拟文件夹。
显示计算机本地内容的虚拟文件夹很可能存储在用户配置文件(%AppData%?)或注册表中的某个位置,并且您已经在备份这些文件夹。
显示远程计算机(FTP,WebDAV,Gmail等)中的内容的虚拟文件夹在您未经过用户特殊确认/选择的情况下可能不应该备份吗?
显示来自插入计算机的硬件的内容的虚拟文件夹并不是用户个人资料恕我直言的一部分。
即使您决定要备份虚拟文件夹,也将如何做?您只是要存储PIDL吗?还是要为每个商品索取IStream
并将其存储起来?只有特定的IShellFolder
类才能知道PIDL格式,并且在查看支持的IStream
实例时,如果没有IShellFolder
的实例,则可能难以理解IShellFolder
备份程序中的数据。您将只能将数据还原到具有该IStream
类可用的计算机上,即使那样,它也可能不支持写入#include <stdint.h>
#include <stdio.h>
// This is typical of the random number generators used in professional games.
// It is less "correct" than mersenne twisters, for example, but much faster.
inline uint32_t fast_rand(int32_t &seed, uint32_t limit) {
// Prevent infinite loops.
//if (limit == 0) return 0;
// Make a mask that has all 1s in the bottom few bits.
// This reduces the number of iterations of the loop to ~1
int leading_zeros = __builtin_clz(limit);
int mask = 0xffffffff >> leading_zeros;
// Loop until our result is in range using rotate and xor.
do {
seed = (seed << 1) ^ ((seed >> 31) & 0xa53a9be9);
} while ((seed & mask) >= limit);
return seed & mask;
}
int main() {
// I'm using two seeds to prevent coupling.
// On their own, their quantiles are pretty flat, but
// in this example they couple, causing conditioning in the results.
int32_t length_seed = (int32_t)0x95abcfad;
int32_t swap_seed = (int32_t)0xba7235fab;
for (int i = 0; i != 10000000; ++i) {
// Note we don't use a std::string. These are very slow.
char chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
auto num_chars = sizeof(chars) - 1;
auto length = fast_rand(length_seed, num_chars-1) + 1;
// Trim the string to the right length.
chars[length] = 0;
// Shuffle the characters.
for (int j = 0; j != length; ++j) {
int swapper = j + fast_rand(swap_seed, length - j);
auto tmp = chars[j];
chars[j] = chars[swapper];
chars[swapper] = tmp;
}
// Print with puts (not iostreams).
puts(chars);
}
}
。
答案 1 :(得分:1)
是否存在一个外壳虚拟文件夹,该文件夹对应于与用户个人资料相关的所有内容?
AFAIK,不,没有。