在 Windows 的 shellapi 文件中定义了一个名为 SHFileOperation() 的外壳函数,它可以用来实现各种文件操作,例如文件的拷贝、删除和移动等,该函数使用起来非常简单,它只有一个指向 SHFILEOPSTRUCT 结构的参数。使用 SHFileOperation()函数时只要填写该专用结构 –SHFILEOPSTRUCT,告诉 Windows 执行什么样的操作,以及其它重要信息就行了。SHFileOperation()的特别之处在于它是一个高级外壳函数,不同于低级文件处理。当调用 SHFileOperation 操作文件时,相应的外壳拷贝处理器(如果有的话)被调用。如在删除某个文件时,SHFileOperation 会将删除的文件放到 Recycle Bin 中。
SHFileOperation() 函数原型为:WINSHELLAPI int WINAPI SHFileOperation(LPSHFILESTRUCT lpFileOp);
LPSHFILESTRUCT 结构格式如下:
在这个结构中,hWnd 是指向发送消息的窗口句柄,pFrom 与 pTo 是进行文件操作的源文件名和目标文件名,它包含文件的路径,对应单个文件的路径字符串,或对于多个文件,必须以 NULL 作为字符串的结尾或文件路径名之间的间隔,否则在程序运行的时候会发生错误。另外,pFrom 和 pTo 都支持通配符 * 和?,这大大方便了开发人员的使用。例如,源文件或目录有两个,则应是:char pFrom[]=“d:/Test1/0d:/Text.txt/0”,它表示对要 D:盘 Test1 目录下的所有文件和 D:盘上的 Text.txt 文件进行操作。字符串中的 ""是 C 语言中的’‘的转义符,’/0’则是 NULL。wFunc 是结构中的一个非常重要的成员,它代表着函数将要进行的操作类型, 它的取值为如下:
·FO_COPY: 拷贝文件 pFrom 到 pTo 的指定位置。
·FO_RENAME: 将 pFrom 的文件名更名为 pTo 的文件名。
·FO_MOVE: 将 pFrom 的文件移动到 pTo 的地方。
·FO_DELETE: 删除 pFrom 指定的文件。
使用该函数进行文件拷贝、移动或删除时,如果需要的时间很长,则程序会自动在进行的过程中出现一个无模式的对话框(Windows 操作系统提供的文件操作对话框),用来显示执行的进度和执行的时间,以及正在拷贝、移动或删除的文件名,此时结构中的成员 lpszProgressTitle 显示此对话框的标题。fFlags 是在进行文件操作时的过程和状态控制标识。它主要有如下一些标识,也可以是其组合:
·FOF_FILESONLY:执行通配符,只执行文件;
·FOF_ALLOWUNDO:保存 UNDO 信息,以便在回收站中恢复文件;
·FOF_NOCONFIRMATION:在出现目标文件已存在的时候,如果不设置此项,则它会出现确认是否覆盖的对话框,设置此项则自动确认,进行覆盖,不出现对话框。
·FOF_NOERRORUI:设置此项后,当文件处理过程中出现错误时,不出现错误提示,否则会进行错误提示。
·FOF_RENAMEONCOLLISION:当已存在文件名时,对其进行更换文提示。
·FOF_SILENT:不显示进度对话框。
·FOF_WANTMAPPINGHANDLE:要求 SHFileOperation() 函数返回正处于操作状态的实际文件列表,文件列表名柄保存在 hNameMappings 成员中。
·SHFILEOPSTRUCT 结构还包含一个 SHNAMEMAPPING 结构的数组,此数组保存由 SHELL 计算的每个处于操作状态的文件的新旧路径。
同时也有一个重要的应用就是:
在进行文件操作时,可以使用 CFile 类中的 Remove()函数来删除一个文件,但是这样的操作将永久性的删除该文件,不能在必要的时候再恢复该文件,解决这个问题的唯一方法就是把文件送到 Windows 系统中的回收站(Recycle Bin)里面,而不是简单的永久性删除它,这样用户就可以在必要的时候恢复这个文件。用这个函数实现编程来实现 Windows 回收站的文件存取操作。
在使用该函数删除文件时必须设置 SHFILEOPSTRUCT 结构中的神秘 FOF_ALLOWUNDO 标志,这样才能将待删除的文件拷到 Recycle Bin,从而使用户可以撤销删除操作。需要注意的是,如果 pFrom 设置为某个文件名,用 FO_DELETE 标志删除这个文件并不会将它移到 Recycle Bin,甚至设置 FOF_ALLOWUNDO 标志也不行,在这里你必须使用全路径名,这样 SHFileOperation 才会将删除的文件移到 Recycle Bin。
代码如下:
fFlags 成员标志间的关系
标志 | 抑制的对话框 | 相关性与优先级 |
FOF_MULTIDESTFILES | 无 | 无 |
FOF_FILESONLY | 无 | 无 |
FOF_SILENT | 如果设置,进度对话框不显示。 | 优先于 FOF_SIMPLEPROGRESS 标志。 |
FOF_SIMPLEPROGRESS | 无 | 为 FOF_SILENT 标志所抑制。 |
FOF_RENAMEONCOLLISION | 如果设置了这个标志,当被移动或拷贝的文件与已存在文件同名时置换对话框不会出现。 | 名字冲突时,如果 FOF_NOCONFIRMATION 标志设置,则操作继续。
如果二者都设置了,则它优先于 FOF_NOCONFIRMATION。即,文件以给定的新名字复制,而不是覆盖。 |
FOF_NOCONFIRMATION | 如果设置,确认对话框在任何情况下都不出现。 | 名字冲突时,引起文件覆盖,除非设置了 FOF_RENAMEONCOLLISION 标志。 |
FOF_NOCONFIRMMKDIR | 抑制请求建立新文件夹的对话框 | 缺省目录作为严重错误产生一个错误消息框。
建立目录的确认对话框作为错误消息框是否显示依赖于 FOF_NOERRORUI 的设置。 |
FOF_NOERRORUI | 抑制所有错误消息框。 | 优先于前一个标志。如果设置,则,缺省目录引起不被处理的异常,并且返回错误码。 |
删除文件
文件删除是一个简单的操作,它仅仅影响到输入缓冲 pFrom,而 pTo 缓冲被忽略。与文件复制一样,操作的详细情况依赖于标志的设置。相关的标志是:
标志 | 值 | 描述 |
FOF_SILENT | 0x0004 | 这个操作不回馈给用户,就是说,不显示进度对话框。相关的消息框仍然显示。 |
FOF_NOCONFIRMATION | 0x0010 | 这个标志使函数对任何遇到的消息框都自动回答 Yes。 |
FOF_ALLOWUNDO | 0x0040 | 如果设置,这个标志强迫函数移动被删除的文件到‘回收站’中。否则,文件将被物理地从磁盘上删除。 |
FOF_FILESONLY | 0x0080 | 设置这个标志导致函数仅仅删除文件,跳过目录项。它仅仅应用于指定通配符的情况。 |
FOF_SIMPLEPROGRESS | 0x0100 | 这导致简化用户界面。使之只有动画而不报告被删除的文件名。代之的是显示 lpszProgressTitle 成员中指定的文字。(Win7 实际中貌似不可用) |
FOF_NOERRORUI | 0x0400 | 如果设置了这个标志,任何发生的错误都不能使消息框显示,而是程序中返回错误码。 |
这里出现的标志最要紧的是 FOF_ALLOWUNDO,它决定文件是否一次就全部删除,或存储到‘回收站’中等候可能的恢复。如果 FOF_ALLOWUNDO 被设置,文件则被移动到回收站,并且这个操作可以被 Undo(尽管可以手动 Undo)。Undo 特征仅在删除下可用,在拷贝与移动中没有等价的操作。
SHFileOperation() 函数的返回值
MSDN 资料中说明,SHFileOperation() 在成功时返回 0,失败时返回非 0 值。显然这是真的,但并不是最有用的解释。重复测试这个函数,可以确信它有非常多的终止方式。事实上,我们经常在系统错误的提示中运行,在有些地方这个函数只是简单地返回从更靠近文件系统的其它程序中获得的返回码。下面列表给出了 SHFileOperation() 返回的最通常的部分错误。
错误码 | 描述 |
2 | 如果你试图重命名多重文件,这个消息就会出现。描述是相当直接的:系统不能找到指定的文件。 |
7 | 在询问是否想要置换给定文件时,你回答了‘取消’,函数就返回这个错误码。它的描述也是相当的不明确—存储控制块被销毁。 |
115 | 在试图重命名文件到不同的文件夹时,发生这个文件系统错。重命名文件只是改变文件名,而不能改变文件夹。 |
117 | 一个 IOCTL 错 (输入 / 输出控制),在目的路径中有错误时或取消了新目录的建立时,这个错误发生了。 |
123 | 你正在试图重命名一个文件,然而你给出的名字是一个已经存在的文件。它也有一个无用的描述:文件名,目录名,或卷标号的语法是不正确的。 |
1026 | 在试图移动或拷贝一个不存在的文件时,出现这个文件系统错。一般地,它提示了,源缓冲中的某些东西应该修改一下。这个错误码弹出一个的错误框,你可以通过设置 FOF_NOERRORUI 标志抑制它的显示。 |