C#中使用API(SHFileOperation)进行文件操作,特别说明了回收站相关参数
2010-03-28 18:23
1071 查看
项目中使用了磁盘阵列柜,每秒有上百兆的数据存入磁盘,这就有了从磁盘删除文件的需求。为了满足这一需求,我做了一个用于删除过期数据的系统服务。说来这个东西本身是很简单的,但是由于数据量的巨大价值磁盘阵列空间容量的巨大(8T,1T=1024G),在实际操作中也遇到了不少麻烦。 需求很简单,遍历磁盘指定目录下的所有目录和文件,根据一个比较规则判定文件是否过期,如果过期就删除。最初的设计也很简单,三个步骤:遍历 -> 过期检测 -> 删除。有了需求和程序框架设计,于是开始实施。
在C#中,DirectoryInfo和FileInfo为我们提供了足够的方法,在程序第一次成型的时候我主要使用了下面的方法:
遍历:DirectoryInfo.GetDirectories(),DirectoryInfo.GetFiles()
删除:DirectoryInfo.Delete(),FileInfo.Delete()
本机使用时效果很好,但实际上服务器运行就出现了问题:磁盘过大,文件过多,导致执行效率极其缓慢,甚至无法遍历出文件夹和文件,删除一个文件就需要好几分钟。当然,这和磁盘I/O有关,需要在有限的I/O下提高效率。
为了提高效率,改用API的方式。使用SHFileOperation来进行文件、文件夹的删除操作。代码见下:
使用API之后,效率明显提高,遍历和删除文件速度明显加快。但尤其值得注意的是:SHFILEOPSTRUCT.fFlags属性,它指定了一些删除操作中的其他属性。这里我想特别提出的是FOF_ALLOWUNDO,望文生义,允许撤销那应当就是删除到回收站了。MSDN上对这个属性的解释是:
Preserve undo information, if possible. Operations can be undone only from the same process that performed the original operation. If, despite earlier warnings against doing so, pFrom does not contain fully-qualified path and file names, this flag is ignored.
它指出:
如果可能,系统将默认这些操作可以撤销。
如果文件、文件夹路径不是全路径,将忽略此属性。
可以看出,这段文字并没有很具体地介绍这个属性。经过我的实际实践得出:
设置 lpFileOp.fFlags |= FOF_ALLOWUNDO和不设置这个属性的效果是一样的,即默认会删除到回收站。
要想直接删除,不进入回收站,我们必须设置lpFileOp.fFlags &= ~FILEOP_FLAGS.FOF_ALLOWUNDO;这一点尤为重要。
当然,这个API除了可以进行删除操作之外,还可以进行其他的文件、文件夹操作,此处不表。
在C#中,DirectoryInfo和FileInfo为我们提供了足够的方法,在程序第一次成型的时候我主要使用了下面的方法:
遍历:DirectoryInfo.GetDirectories(),DirectoryInfo.GetFiles()
删除:DirectoryInfo.Delete(),FileInfo.Delete()
本机使用时效果很好,但实际上服务器运行就出现了问题:磁盘过大,文件过多,导致执行效率极其缓慢,甚至无法遍历出文件夹和文件,删除一个文件就需要好几分钟。当然,这和磁盘I/O有关,需要在有限的I/O下提高效率。
为了提高效率,改用API的方式。使用SHFileOperation来进行文件、文件夹的删除操作。代码见下:
using System; using System.Runtime.InteropServices; namespace FileDirectoryAPI { public class DeleteAPI { [DllImport("shell32.dll")] private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp); /// /// 执行删除。成功返回空,否则返回错误信息。 /// /// /// public static string Delete(string path) { SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT(); lpFileOp.wFunc = wFunc.FO_DELETE; lpFileOp.pFrom = path + "/0"; lpFileOp.fFlags = FILEOP_FLAGS.FOF_NOCONFIRMATION | FILEOP_FLAGS.FOF_NOERRORUI | FILEOP_FLAGS.FOF_SILENT; lpFileOp.fFlags &= ~FILEOP_FLAGS.FOF_ALLOWUNDO; lpFileOp.fAnyOperationsAborted = false; int n = SHFileOperation(ref lpFileOp); if (n == 0) return string.Empty; string tmp = GetErrorString(n); //.av 文件正常删除了但也提示 402 错误,不知道为什么。屏蔽之。 if ((path.ToLower().EndsWith(".av") && n.ToString("X") == "402")) return string.Empty; return string.Format("{0}({1})", tmp, path); } private struct SHFILEOPSTRUCT { public IntPtr hwnd; public wFunc wFunc; public string pFrom; public string pTo; public FILEOP_FLAGS fFlags; public bool fAnyOperationsAborted; public IntPtr hNameMappings; public string lpszProgressTitle; } private enum wFunc { FO_MOVE = 0x0001, FO_COPY = 0x0002, FO_DELETE = 0x0003, FO_RENAME = 0x0004 } private enum FILEOP_FLAGS { FOF_MULTIDESTFILES = 0x0001, //pTo 指定了多个目标文件,而不是单个目录 FOF_CONFIRMMOUSE = 0x0002, FOF_SILENT = 0x0044, // 不显示一个进度对话框 FOF_RENAMEONCOLLISION = 0x0008, // 碰到有抵触的名字时,自动分配前缀 FOF_NOCONFIRMATION = 0x10, // 不对用户显示提示 FOF_WANTMAPPINGHANDLE = 0x0020, // 填充 hNameMappings 字段,必须使用 SHFreeNameMappings 释放 FOF_ALLOWUNDO = 0x40, // 允许撤销 FOF_FILESONLY = 0x0080, // 使用 *.* 时, 只对文件操作 FOF_SIMPLEPROGRESS = 0x0100, // 简单进度条,意味者不显示文件名。 FOF_NOCONFIRMMKDIR = 0x0200, // 建新目录时不需要用户确定 FOF_NOERRORUI = 0x0400, // 不显示出错用户界面 FOF_NOCOPYSECURITYATTRIBS = 0x0800, // 不复制 NT 文件的安全属性 FOF_NORECURSION = 0x1000 // 不递归目录 } //更多错误代码见:ms-help://MS.MSDNQTR.v90.chs/shellcc/platform/shell/reference/functions/shfileoperation.htm private static string GetErrorString(int n) { if (n == 0) return string.Empty; string code = n.ToString("X").ToUpper(); switch (code) { case "74": return "The source is a root directory, which cannot be moved or renamed."; case "76": return "Security settings denied access to the source."; case "7C": return "The path in the source or destination or both was invalid."; case "10000": return "An unspecified error occurred on the destination."; case "402": return "An unknown error occurred. This is typically due to an invalid path in the source or destination. This error does not occur on Windows Vista and later."; default: return code; } } } }
使用API之后,效率明显提高,遍历和删除文件速度明显加快。但尤其值得注意的是:SHFILEOPSTRUCT.fFlags属性,它指定了一些删除操作中的其他属性。这里我想特别提出的是FOF_ALLOWUNDO,望文生义,允许撤销那应当就是删除到回收站了。MSDN上对这个属性的解释是:
Preserve undo information, if possible. Operations can be undone only from the same process that performed the original operation. If, despite earlier warnings against doing so, pFrom does not contain fully-qualified path and file names, this flag is ignored.
它指出:
如果可能,系统将默认这些操作可以撤销。
如果文件、文件夹路径不是全路径,将忽略此属性。
可以看出,这段文字并没有很具体地介绍这个属性。经过我的实际实践得出:
设置 lpFileOp.fFlags |= FOF_ALLOWUNDO和不设置这个属性的效果是一样的,即默认会删除到回收站。
要想直接删除,不进入回收站,我们必须设置lpFileOp.fFlags &= ~FILEOP_FLAGS.FOF_ALLOWUNDO;这一点尤为重要。
当然,这个API除了可以进行删除操作之外,还可以进行其他的文件、文件夹操作,此处不表。
相关文章推荐
- c#中使用api(shfileoperation)进行文件操作,特别详解了回收站相关参数
- C#中使用API(SHFileOperation)进行文件操作,特别说明了回收站相关参数
- c#使用API进行模拟鼠标点击 底层操作同样简单
- Visual Studio 2017中使用正则修改部分内容 如何使用ILAsm与ILDasm修改.Net exe(dll)文件 C#学习-图解教程(1):格式化数字字符串 小程序开发之图片转Base64(C#、.Net) jquery遍历table为每一个单元格取值及赋值 。net加密解密相关方法 .net关于坐标之间一些简单操作
- 使用C# 怎么生成.db后缀的文件,并且能够使用sql语言进行读取等 操作
- 使用gulp相关插件进行api的跨域访问并监控文件的变化的简单处理
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- 使用文件映射的方式进行共享数据中CreateFileMapping、MapViewOfFile函数参数说明
- 使用servlet3.0提供的API来进行文件的上传操作
- 使用FILE文件指针进行文件的操作相关函数
- linux下文件的读写操作、字符串的处理操作,多线程操作等相关函数使用说明
- 如何使用C#对虚拟磁盘文件(VHD)进行操作
- 使用微软Kinect进行手势识别操作的一个简单范例(WPF-C#)
- Linux使用 tar命令-g参数进行增量+差异备份、还原文件
- VC中使用CFileDialog进行文件操作
- Win10下python3和python2同时安装并解决pip共存问题 特别说明,本文是在Windows64位系统下进行的,32位系统请下载相应版本的安装包,安装方法类似。 使用python开
- .NET下使用C#操作XML文件
- C#文件操作相关语句 - 大全
- 使用ssh进行远程连接以及远程跳板以及scp远程上传下载文件说明
- C#中使用Emgucv实现对多波段Img文件的滤波操作