管理文件系统(二)

MSDN 2005 -> Win32 和 COM 开发 -> User Interface -> Windows User Experience -> Windows Shell -> Windows Shell -> Shell Programmer's Guide -> Shell Basics -> Managing the File System 

我用不好自己的母语,写不出文笔流畅、内容生动的文章。不过从这篇文章来看,有些外国人也一样用不好自己的母语,写出的文字一样地啰嗦,一样地一句话反复说几遍,一样地段落中的各个句子间逻辑不够连贯。不过,我翻译的时候是尽量保证语句通顺,意思表达清楚的,比某些翻译出版的书的翻译质量高了不知道多少。 

Shell提供了很多种管理文件系统的方法。Shell提供的函数SHFileOperation,可以让应用以编程的方法进行文件的移动、复制、重命名和删除。除此之外,Shell还提供了其他额外的文件管理能力。

  • HTML文档可以连接到相关文件,比如说图形文件或者样式表。被移动或者复制时,其连接到的文件也同时被自动移动或者复制。
  • 对于对多用户系统,可以基于每用户进行文件管理。用户可以方便地访问自己的数据文件,但不能访问其他用户的文件。
  • 增加或者修改文件时,可以将其添加到Shell的最近文档列表。用户选择开始菜单中的文档命令时,最近文档列表会出现。

本文先讨论这些文件管理技术,然后概要介绍如何使用Shell进行文件的移动、复制、重命名和删除,以及如何管理回收站中的对象。

每用户文件管理

Windows 2000的Shell可以把文件关联到某个用户,这样文件就对其他用户是隐藏的。用文件系统的术语来说,用户文件保存在通常是C:/Documents and Settings/Username/的用户配置文件夹中。这个特征可以让多人使用同一台计算机,并且保证各自文件的私密性。这也为管理员和应用程序提供了一种保存初始化(.ini)或者链接(.lnk)文件的直接方法。应用程序可以为每个用户保存不同的状态,并且在必要时恢复特定状态。此外还有一个配置文件夹保存对所有用户公用的信息。

确定当前登录的用户和其配置文件的位置是不太方便的,所以它被定义为用CSIDL标识的特别文件夹。比如说,每用户的程序文件夹的CSIDL是CSIDL_PROGRAMS。如果调用SHGetFolderLocation或者SHGetFolderPath,传入某个每用户CSIDL,函数会返回当前登录用户相关的PIDL或者路径。如果要获取用户配置文件夹的路径或者PIDL,则使用CSIDL_PROFILE  

我的文档和我的图片文件夹

我的文档是桌面上的标准图标之一。它包含当前用户的文档文件。我的文档是个虚拟文件夹,它在名字空间中直接位于桌面之下,但实际上却是文件系统中保存用户文档的位置的别名。

我的文档我的图片文件夹的目的是在可能有多个用户的系统中,为用户提供一种安全地访问其文档和图片文件的方法。系统为每个用户分配不同的文件夹用于保存其文件。比如说,文件系统中用户文档文件夹通常是C:/Documents and Settings/Username/My Documents。然而用户并不需要了解这个物理位置,只需要简单地通过我的文档图标访问其文件就可以了。

应用程序通常不需要了解当前登录的用户,以及其我的文档文件夹的位置。应用程序可以用桌面的ParseDisplayName方法获取桌面上我的文档图标的PIDL。用于标识我的文档文件夹的解析名不是一个文件路径,而是::{450d8fba-ad25-11d0-98a8-0800361b1103}。大括号表达式是我的文档的全局唯一标识符的文本表示。比如说,要获取我的文档的PIDL,程序可以使用下面的语句: 

hr psfDeskTop->ParseDisplayName(NULL,NULL, 
                                  L"::{450d8fba-ad25-11d0-98a8-0800361b1103}", 
                                  &chEaten, 
                                  &pidlDocFiles, 
                                  NULL);

使用SHGetFolderLocationCSIDL_MYDOCUMENTS常量也可以: 

hr SHGetFolderLocation(NULL, 
                         CSIDL_MYDOCUMENTS, 
                         NULL,
                         0,
                         &pidlDocFiles);

取得我的文档的PIDL后,就可以像普通文件夹那样对其进行处理了:枚举其内容、解析、绑定、执行其他任何有效的文件夹操作。Shell会自动地将对我的文档的修改映射到合适的文件系统文件夹。

如果需要访问实际包含用户文档的文件系统文件夹,可以把CSIDL_PERSONAL传递给SHGetFolderLocation。函数会返回显示在当前用户我的文档文件夹中的文件系统文件夹的PIDL。

连接的文件

HTML文档通常包含很多相关的图形文件、样式表文件、Java脚本文件等。移动或者复制主HTML文档时,通常也需要移动或者复制相关的文件,以避免破坏文档中的链接。然而,直到现在才有不需要分析文件内容,就可以确定与给定的HTML文档相关的文件的方法,这就是Windows 2000提供的文件连接。如果启用了文件连接,移动或者复制主文档时,所有相关文件会一起移动或者复制。

要创建连接文件组,主文档的扩展名必须是.htm或者.html。在主文档所在文件夹中创建一个子文件夹,其名字必须与主文档去掉扩展名后的名字相同,而扩展名是下列之一。最常见的扩展名是.files或者_files。比如说,如果主文档的名字是MyDoc.htm,则子文件夹可能是MyDoc_files。

对于某些语言,可以创建本地化而等价的_files子文件夹。下面是创建子文件夹时可以添加到文档名后的有效字符串列表。注意,有些字符串的第一个字符是-(减号),而不是_(下划线)或者.(点)。

 

"_archivos""_arquivos""_bestanden""_bylos"
"-Dateien""_datoteke""_dosyalar""_elemei"
"_failid""_fails""_fajlovi""_ficheiros"
"_fichiers""-filer"".files""_files"
"_file""_fitxers""_fitxategiak""_pliki"
"_soubory""_tiedostot"

注意:扩展名是大小写敏感的。比如说,对于上面的例子,名为MyDoc_Files的子文件夹不会被连接到MyDoc.htm。

文件连接是否启用由注册表中的一个二进制值NoFileFolderConnection控制,其位置如下:

HKEY_CURRENT_USER
Software
Microsoft
Windows
CurrentVersion
Explorer

通常这个值是没有定义的,表示默认文件连接被启用。如果有必要,添加这个值并且设置为1,就可以禁用文件连接了。要再次启用文件连接,把NoFileFolderConnection设置为0就可以了。

移动、复制、重命名和删除文件
名字空间不是静止不变的,应用程序通常需要通过下列操作来管理文件系统:

  • 复制对象到其他文件夹

  • 移动对象到其他文件夹

  • 删除对象

  • 重命名对象


SHFileOperation可以进行所有这些操作。函数要求输入一个或者多个源文件,并生成相应的目标文件。在删除操作中,系统试图把要删除的文件放入到回收站中。此外 也可以用拖放功能来移动文件。
要使用SHFileOperation,必须填充SHFILEOPSTRUCT结构体,然后把它传递给函数。结构体的主要成员是pFrompTo

  • pFrom成员是以两个空字符结束的字符串,表示一个或者多个源文件名。文件名可以是全限定路径名或者像*.*这样的标准DOS通配符。虽然这个成员被声明为以空字符结束的字符串,但实际上它是用于保存多个文件名的缓冲区。每个文件名必须以通常的单个空字符结束。在最后一个文件名后面必须再加一个空字符来表示pFrom的结束。

  • pTo成员跟pFrom一样,也是以两个空字符结束的字符串,它表示一个或者多个全限定的目标名。多个名字以与pFrom相同的方式存放到pTo中。如果pTo包含多个文件名,必须在fFlags成员中设置FOF_MULTIDESTFILES标志。pTo的用法跟操作相关:

  1. 对于复制和移动操作,如果所有文件复制或者移动到单个目录中,则pTo包含全限定的目录名。如果各个文件的目标目录不同,pTo也可以为每个源文件包含一个全限定的目录或者文件名。如果目标目录不存在,系统会创建它。

  2. 对于重命名操作,pTo为pFrom中的每个源文件包含一个全限定的目标文件名。

  3. 对于删除操作,pTo没有使用。


通知Shell
在使用SHFileOperation进行文件移动、复制、重命名或者删除操作后,或者进行其他任何影响名字空间的操作后,应该通知Shell发生的变化。完成后应该通知Shell的操作有:
  • 增加或者删除文件或者文件夹

  • 移动、复制或者重命名文件或者文件夹

  • 修改文件关联

  • 修改文件属性

  • 增加或者移除驱动器或者存储媒体

  • 创建或者禁用标准文件夹

  • 修改系统图像列表

应用程序通过SHChangeNotify向Shell通知变化的细节,这样Shell就可以更新名字空间的图像,以精确反映新的状态。 使用SHFileOperation管理文件的简单例子
下面的控制台程序代码展示了使用SHFileOperation把文件从一个目录复制到另一个目录。为使代码简单,源目录C:/My_Docs和目标目录C:/My_Docs2被硬编码到程序中。
<…… 省略示例代码 ……>
程序首先获取桌面的IShellFolder接口指针。然后把源目录的全限定路径名传递给ParseDisplayName以获取其PIDL。注意ParseDisplayName要求目录路径使用Unicode字符串。随后程序绑定到源目录,使用IShellFolder接口获取枚举对象的IEnumIDList接口。

枚举到源目录中的每个文件时,使用GetDisplayNameOf获取其名字。设置了SHGDN_FORPARSING标志,这样GetDisplayNameOf返回文件的解析名。文件路径,包括表示结束的空字符,连接起来成为单个数组szSourceFiles。最后一个路径名后添加了第二个空字符以正确地结束整个数组。

枚举完成后,程序为SHFILEOPSTRUCT结构体成员赋值。注意赋给pTo用以指定目标路径的数组也应该以两个空字符结束。本例中,数组简单地包含赋给pTo的字符串。因为是控制台程序,所以使用了FOF_SILENTFOF_NOCONFIRMATIONFOF_NOCONFIRMMKDIR标志以阻止出现任何对话框。SHFileOperation返回后,调用SHChangeNotify通知Shell发生的变化。然后程序执行通常的清理并返回。


添加文件到Shell的最近文档列表中


Shell为每个用户维护一个最近新增或者修改的文档列表。点击开始菜单中的“文档”命令就可以显示到这些文件的链接列表。跟我的文档类似,每个用户都有一个文件系统目录用于保存实际的链接。要获取当前用户最近文档目录的PIDL,可以以参数CSIDL_RECENT调用SHGetFolderLocation,或者用SHGetFolderPath获取其路径。

可以用本系列前面文章讨论的技术枚举最近文档文件夹的内容。然而,程序不应该像普通文件系统文件夹那样修改其内容。如果这么做了,Shell的最近文档列表将不会正确更新,不会正确地显示在开始菜单中。应该用SHAddToRecentDocs向用户的最近文档文件夹添加文档链接。Shell会在合适的文件夹添加文档链接,同时更新开始菜单中的最近文档列表。也可以用这个函数来清除最近文档列表。  

菊子曰 这就是 菊子曰啦!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值