常见资源管理器概念

Shell 命名空间 将文件系统和 Shell 管理的其他对象组织到单个树状层次结构中。 从概念上讲,它是更大且更具包容性的文件系统版本。

简介

Shell 的主要职责之一是管理和提供对构成系统的各种对象的访问。 这些对象中最众多、最熟悉的是驻留在计算机磁盘驱动器上的文件夹和文件。 但是,Shell 也会管理许多非文件系统或 虚拟 对象。 示例包括:

  • 网络打印机
  • 其他联网计算机
  • 控制面板应用程序
  • 回收站

某些虚拟对象根本不涉及物理存储。 例如,打印机对象包含指向联网打印机的链接集合。 其他虚拟对象(如回收站)可能包含存储在磁盘驱动器上的数据,但需要以与普通文件不同的方式进行处理。 例如,虚拟对象可用于表示存储在数据库中的数据。 就 命名空间而言,数据库中的各种项可以作为单独的对象显示在 Windows 资源管理器中,即使它们都存储在单个磁盘文件中。

虚拟对象甚至可能位于远程计算机上。 例如,为了便于漫游,用户的文档文件可能存储在服务器上。 为了允许用户从多台台式电脑访问其文件,他们当前使用的台式电脑上的“我的文档”文件夹将指向服务器,而不是台式电脑的硬盘。 其路径将包括映射的网络驱动器或 UNC 路径名称。

与文件系统一样, 命名空间包括两种基本类型的对象:文件夹和文件。 文件夹对象是树的 节点 ;它们是文件对象和其他文件夹的容器。 文件对象是树的 叶子 ;它们是普通磁盘文件或虚拟对象,如打印机链接。 不属于文件系统的文件夹有时称为 虚拟文件夹

与文件系统文件夹一样,虚拟文件夹的集合通常因系统而异。 虚拟文件夹有三类:

  • 在所有系统上找到的标准虚拟文件夹,例如回收站。
  • 具有标准名称和功能的可选虚拟文件夹,但可能并非在所有系统上都存在。
  • 用户安装的非标准文件夹。

与文件系统文件夹不同,用户无法自行创建新的虚拟文件夹。 他们只能安装非 Microsoft 开发人员创建的。 因此,虚拟文件夹的数量通常比文件系统文件夹的数量少得多。 有关如何实现虚拟文件夹的讨论,请参阅 命名空间扩展

可以在 Windows 资源管理器的资源管理器栏中查看命名空间的构造方式的可视化表示形式。 例如,Windows 资源管理器的以下屏幕截图显示了相对简单的命名空间。

显示 shell 命名空间视图的屏幕截图

命名空间层次结构的最终根是桌面。 根目录正下方是多个虚拟文件夹,例如“我的电脑”和“回收站”。

可以看到,各种磁盘驱动器的文件系统是较大命名空间层次结构的子集。 这些文件系统的根是“我的电脑”文件夹的子文件夹。 “我的计算机”还包括任何映射的网络驱动器的根。 树中的其他节点(如“我的文档”)是虚拟文件夹。

标识命名空间对象

在使用命名空间对象之前,必须先有一种标识它的方法。 文件系统中的对象可以具有MyFile.htm等名称。 由于系统中的其他位置可能存在具有该名称的其他文件,因此唯一标识文件或文件夹需要完全限定的路径,例如“C:\MyDocs\MyFile.htm”。 此路径基本上是文件系统根目录 C:\路径中所有文件夹的有序列表,以文件结尾。

在命名空间的上下文中,路径对于标识位于命名空间的文件系统部分中的对象仍然非常有用。 但是,它们不能用于虚拟对象。 相反,Shell 提供了可与任何命名空间对象一起使用的替代标识方法。

项 ID

在文件夹中,每个对象都有一个 项 ID,即文件或文件夹名称的功能等效项 ID。 项 ID 实际上是 SHITEMID 结构:

typedef struct _SHITEMID { 
    USHORT cb; 
    BYTE   abID[1]; 
} SHITEMID, * LPSHITEMID;

abID 成员是对象的标识符。 abID 的长度未定义,其值由包含 对象的文件夹确定。 由于没有标准定义 文件夹分配 abID 值的方式,因此它们仅对关联的文件夹对象有意义。 应用程序应将它们视为标识特定文件夹中对象的标记。 由于 abID 的长度各不相同, 因此 cb 成员保留 SHITEMID 结构的大小(以字节为单位)。

由于项 ID 对显示目的没有用,因此包含对象的文件夹通常会为其分配显示名称。 这是 Windows 资源管理器在显示文件夹内容时使用的名称。 有关如何处理显示名称的详细信息,请参阅 从文件夹中获取信息

项目 ID 列表

项目 ID 很少单独使用。 通常,它是项 ID 列表的一部分,其用途与文件系统路径相同。 但是,项 ID 列表不是用于路径的字符串,而是 ITEMIDLIST 结构。 此结构是一个或多个项 ID 的有序序列,以两字节 NULL 结尾。 项 ID 列表中的每个项 ID 对应于一个命名空间对象。 其顺序定义命名空间中的路径,非常类似于文件系统路径。

下图显示了对应于C:\MyDocs\MyFile.htm的 ITEMIDLIST 结构的示意图表示形式。 每个项 ID 的显示名称显示在其上方。 abID 成员的不同宽度是任意的;它们说明了此成员的大小可能有所不同的事实。

pidl 的示意图

PIDL

对于 Shell API,命名空间对象通常通过指向其 ITEMIDLIST 结构的指针或指向 PIDL) 项标识符列表 (指针来标识。 为方便起见,在本文档中,术语 PIDL 通常是指结构本身,而不是指向它的指针。

上图中显示的 PIDL 称为 完整 PIDL 或 绝对 PIDL。 完整的 PIDL 从桌面开始,包含路径中所有中间文件夹的项目 ID。 它以对象的项 ID 结尾,后跟终止的双字节 NULL。 完整 PIDL 类似于完全限定的路径,并且唯一标识 Shell 命名空间中的对象。

不经常使用完整的 PIDL。 许多函数和方法需要 相对 PIDL。 相对 PIDL 的根是文件夹,而不是桌面。 与相对路径一样,构成 结构的项 ID 系列定义两个 对象之间的命名空间中的路径。 尽管它们不唯一标识对象,但它们通常小于完整的 PIDL,并且足以用于许多目的。

最常用的相对 PIDL( 单级 PIDL)相对于对象的父文件夹。 它们仅包含对象的项 ID 和终止 NULL。 多层 PIDL 也用于多种用途。 它们包含两个或多个项 ID,通常通过一系列一个或多个子文件夹定义从父文件夹到对象的路径。 请注意,单级 PIDL 仍可以是完全限定的 PIDL。 具体而言,桌面对象是桌面的子级,因此其完全限定的 PIDL 仅包含一个项 ID。

获取文件夹的 ID 中所述,Shell API 提供了多种检索对象的 PIDL 的方法。 获得它后,通常只需在调用其他 Shell API 函数和方法时使用它来标识对象。 在此上下文中,PIDL 的内部内容不透明且无关紧要。 出于此讨论的目的,请将 PIDL 视为表示特定命名空间对象的标记,并重点介绍如何将它们用于常见任务。

分配 PIDL

尽管 PIDL 与路径有一些相似之处,但使用它们需要一些不同的方法。 主要区别在于如何为它们分配和解除分配内存。

与用于路径的字符串一样,必须为 PIDL 分配内存。 如果应用程序创建 PIDL,则必须为 ITEMIDLIST 结构分配足够的内存。 对于此处讨论的大多数情况,Shell 会创建 PIDL 并处理内存分配。 无论分配 PIDL 是什么,应用程序通常负责在不再需要 PIDL 时解除分配 PIDL。

使用 CoTaskMemAlloc 函数分配 PIDL,使用 CoTaskMemFree 函数解除分配。