【问题标题】:What folders make up a user's profile哪些文件夹构成了用户的个人资料
【发布时间】: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


【解决方案1】:

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

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

特别适用于将自己的文件夹之一添加到已知文件夹系统的独立软件供应商 (ISV)。

这意味着你将永远无法列出所有这些,无论是已经发明的还是其他的。

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

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

    每个用户的文件夹是存储在每个用户的配置文件下并且只能由该用户访问的文件夹。

    (我认为它们实际上是指默认情况下存储在用户配置文件中的文件夹。)

  • IKnownFolder::GetFolderDefinition 查找父文件夹并遍历父树以查看它是否以 FOLDERID_Profile 结尾。

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

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

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

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

显示来自远程计算机(FTP、WebDAV、Gmail 等)内容的虚拟文件夹可能不是您不应该在没有用户特别确认/选择的情况下备份的东西?

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

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

【讨论】:

  • ...*你*写了那个Known Folder Info工具;那个工具很棒!花了我一点时间,但我现在明白了你所说的“父母 ID”是什么意思。是的,我将绑定到IStreams;我已经习惯了——而不是假设或要求一个文件系统。但我看到您必须非常小心不要使用 Shell API 来读取文件夹内容。如果你不小心进入了用户的Desktop文件夹,那么你将开始枚举整个计算机;因为Desktop 在shell 命名空间的根附近。
  • 这样我就可以找到属于该配置文件的所有 KNOWNFOLDERS。但我必须弄清楚如何排除彼此的“孩子”文件夹。
  • 您可以从 PIDL 中获取已知的文件夹 ID,因此每次您要进入文件夹时都可以检查。
  • 我在检查 pidls 时发现的危险是,一旦您点击“桌面”文件夹,计算机上的 所有内容 都会成为它的孩子(无论实际情况是否属实)文件系统与否)。
  • 例如当您使用 shell/pidl 规则时,"D:\Users\ian\Desktop 是 "C:\Users\ian" 的父级。
【解决方案2】:

是否存在与用户个人资料相关的所有内容对应的 shell 虚拟文件夹?

AFAIK,不,没有。

【讨论】:

    猜你喜欢
    • 2016-08-31
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    相关资源
    最近更新 更多