哪些文件夹构成了用户的配置文件

What folders make up a user's profile

简短版

是否有 IShellItem 对应于用户的整个个人资料?

或给定所有已知的 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 允许用户配置 某些 特殊文件夹以移动到自定义位置:

这意味着某些文件夹实际上可以存在于“个人资料”文件夹之外:

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 对应 virtually到用户个人资料中的所有内容。

与查看 This PC 文件夹 (CSIDL_DRIVES) 的方式相同 (formerly known as My Computer),它是一个虚拟 shell 文件夹,其中包含:

This PC
├── 3D Objects
├── Desktop
├── Documents
├── Downloads
├── Music
├── Pictures
╰── Videos

太棒了;它是一个虚拟文件夹,其中包含构成用户配置文件的文件夹(无论这些文件夹实际位于何处)。

不幸的是,这有两个缺点:

“因此只需备份 所有 个表示每个用户文件夹的 CSIDL”

我想我可以简单地查看每个 CSIDL,剔除任何 IShellItem 是另一个 I[=228 的子项=]Item(待办事项:弄清楚如何做),然后只备份那些:

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 不完整(并且已弃用)。例如:

改用 KNOWNFOLDERID

我们将切换到现代 KNOWNFOLDERS。这样我会得到:

除了 KnownFolders 没有帮助

我列举所有已知 KNOWNFOLDER constants 的计划失败有两个原因。

在编写我的应用程序后发明的任何常量都将丢失 - 丢失备份用户配置文件数据。对于备份应用程序来说不是一件好事。 "All Known Folders on a system can be enumerated."

但更重要的是我不知道哪些KNOWNFOLDERS每个用户。例如:

Apps 是每个用户吗?仅仅因为一个文件夹没有文件系统路径,并不意味着它不存在,或者我无法读取它,或者我无法枚举它的文件,或者我无法备份它的内容

当使用现代(即Windows 95)Shell API枚举文件和文件夹时,您可以很好地读取这些文件。

通过 USB 将手机插入电脑。您可以浏览文件,并使用 IShellItem api 枚举它们 - 即使它们没有文件系统路径。

总结

是否有 shell 虚拟文件夹对应于与用户配置文件相关的 所有内容

Is there a shell virtual folder that corresponds to everything related to a user's profile?

据我所知,不,没有。

我认为不存在包含所有用户特殊文件夹的文件夹,最接近的是 FOLDERID_UsersFiles 文件夹,但我认为这与仅查看个人资料文件夹几乎相同。

已知文件夹可以由 3rd 方应用程序创建,请参阅 IKnownFolderManager::RegisterFolder:

Used particularly by independent software vendors (ISVs) that are adding one of their own folders to the known folder system.

这意味着您永远无法列出所有这些技术,无论是已经发明的还是其他方式。

我可以想到 3 种可能的方法来处理这个问题,它们都涉及使用 IKnownFolderManager 来枚举已安装的已知文件夹。

  • IKnownFolder::GetCategory 并查找 KF_CATEGORY_PERUSER 个文件夹。

    Per-user folders are those stored under each user's profile and accessible only by that user.

    (我认为它们的真正意思是默认情况下存储在用户配置文件中的文件夹。)

  • IKnownFolder::GetFolderDefinition找到父文件夹,走父树看是否以FOLDERID_Profile.

  • 结尾
  • IKnownFolder::GetPath(KF_FLAG_DEFAULT_PATH,...) 并检查此路径是否在用户配置文件中。我认为没有理由选择这种方法。

在大多数情况下,前两种方法应该给出相同的结果,但这取决于它们的注册方式。默认情况下,每个用户类别文件夹理论上可以位于配置文件文件夹之外 AFAIK 并且虚拟文件夹可能将配置文件文件夹作为其父级。使用像 Known Folders Browser or Known Folder Info 这样的工具可能有助于可视化这些差异。

这不包括像 FOLDERID_AppsFolder 这样的大多数虚拟文件夹,但我不确定您是否应该备份虚拟文件夹。

显示计算机本地内容的虚拟文件夹很可能存储在用户配置文件 (%AppData%?) 或注册表中的某处,并且您已经在备份这些文件夹。

显示来自远程机器(FTP、WebDAV、Gmail 等)的内容的虚拟文件夹可能不是您应该备份的东西,如果用户没有特殊 confirmation/selection?

显示插入机器的硬件内容的虚拟文件夹并不是用户配置文件恕我直言的一部分。

即使您决定要备份虚拟文件夹,您打算怎么做?您只是要存储 PIDL 吗?还是您要为每个项目请求 IStream 并存储它? PIDL 格式可能只有那个特定的 IShellFolder class 知道,当你没有那个 IShellFolder 的实例时,理解 IStream 可能会有问题在备份程序中查看备份数据时。您只能将数据恢复到具有 IShellFolder class 可用的机器,即使那样,它也可能不支持写入 IStreams.