我可以在 .NET 中使用 FileInfo.CopyTo() 显示文件复制进度吗?
我在 C# (.NET 2.0 Framework) 中创建了一个复制实用程序,用于复制文件、目录和递归子目录等。该程序有一个 GUI,显示当前正在复制的文件、当前文件编号(顺序)、总数要复制的文件数量以及复制操作完成的百分比。 还有一个进度条,基于当前文件/总文件。
我的问题与复制大文件有关。 我一直无法找到一种方法来指示大文件的总复制进度(使用我当前使用 FileInfo.CopyTo 方法的类结构)。 作为一种解决方法,我将文件复制操作和 GUI 显示分离到它们自己的线程中,并设置一个视觉提示来显示工作正在完成。 至少用户知道程序没有冻结并且仍在复制文件。
如果能够根据字节总数显示进度,或者从 FileInfo.CopyTo 方法触发某种类型的事件来指示从当前文件复制的字节总数,那就更好了。
我知道 FileInfo.Length 属性,所以我确信有一种方法 MacGuyver 我自己的事件基于此,并且在读取更新的事物的 GUI 端有一个处理程序(可能基于检查 FileInfo.Length 属性)。使用某种类型的计时器的目标对象的长度属性?)。
有谁知道我忽略的一种方法可以做到这一点。 如果我可以避免它,我宁愿不重写我的类以通过流复制字节并以这种方式跟踪它(尽管我认为我可能会坚持走这条路)。
PS - 我现在坚持使用 .NET 2.0 框架,因此任何需要仅在 >= 3.0 中可用的功能的解决方案都不适合我。
PPS - 我对任何 .NET 语言类型的解决方案持开放态度,而不仅仅是 C#。
I've created a copy utility in c# (.NET 2.0 Framework) that copies files, directories and recursive sub directories etc. The program has a GUI that shows the current file being copied, the current file number (sequence), the total number of files to be copied and the percentage completed for the copy operations. There is also a progress bar, that is based on current file / total files.
My problem is related to copying large files. I've been unable to find a way to indicate the total copy progress of a large file (using my current class structure that utilitzes FileInfo.CopyTo method). As a workaround I've separated the file copy operations and GUI display to their own threads and set up a visual cue to show that work is being done. At least the user is aware that the program isn't frozen and is still copying files.
It would be nicer to be able to show the progress based on the total number of bytes or have some type of event that fires from the FileInfo.CopyTo method that indicates the total number of bytes copied from the current file.
I'm aware of the FileInfo.Length property, so I'm sure there is a way MacGuyver my own event that is based on this and have a handler on the GUI side of things reading the updates (maybe based on checking the FileInfo.Length property of the destination object using some type of timer?).
Does anyone know of a way to do this that I'm overlooking. If I can avoid it, I'd rather not rewrite my class to copy bytes through a stream and track it that way (though I'm thinking I might be stuck with going that route).
PS - I'm stuck with the .NET 2.0 framework for now, so any solution that requires features available in >= 3.0 only are not an option for me.
PPS - I'm open to solutions in any .NET language variety, not only c#.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
FileInfo.CopyTo 基本上是 kernel32.dll 中 Win32 API 调用“CopyFile”的包装器。 该方法不支持进度回调。
但是,CopyFileEx 方法可以,您可以在几分钟内围绕它编写自己的 .NET 包装器,如下所述:
http://www. pinvoke.net/default.aspx/kernel32.CopyFileEx
The FileInfo.CopyTo is basically a wrapper around the Win32 API call "CopyFile" in the kernel32.dll. This method does not support progress callback.
However, the CopyFileEx method does, and you can write your own .NET wrapper around it in a few minutes, like it is described here:
http://www.pinvoke.net/default.aspx/kernel32.CopyFileEx
我还使用了标记的答案中提供的实现。 不过,我随后创建了一个包装器来提供更好的™ API 以供从 .NET 使用。
用法:
实现
I also used the implementation provided in the marked answer. However I then created a wrapper to provide a nicer™ API to use from .NET.
Usage:
Implementation
我知道我来晚了,但我为
CopyFileEx
做了一个包装器,它返回一个Task
并接受CancellationToken
和 <代码>IProgress<双>。 不幸的是,它在 .NET 2.0 框架中不起作用,但对于使用 4.5 的任何人来说,这允许您使用await
关键字。I know I'm a bit late to the party, but I made a wrapper for
CopyFileEx
that returns aTask
and accepts aCancellationToken
andIProgress<double>
. Unfortunately it won't work in the .NET 2.0 framework, but for anyone using 4.5, this allows you to use theawait
keyword.看在上帝的份上,不要使用流来实现您自己的文件复制! Gaspar 提到的 Win32 CopyFile API 调用能够利用例如 DMA,而我敢打赌 Will 编写的代码不会“智能”到足以做到这一点。
CopyFileEx 会正确对待您,或者您可以实现一个 BackgroundWorker 来监视目标文件大小的增长并使用该信息更新进度条。 后一种方法可以为您节省 PInvoke,但从长远来看,前一种方法可能更干净一些。
For the love of God do not implement your own file copy using streams! The Win32 CopyFile API call that Gaspar mentioned is able to take advantage of e.g. DMA, whereas I'd bet dollars to doughnuts that the code Will wrote would not be "smart" enough to do that.
CopyFileEx will treat you right, or you could implement a BackgroundWorker that watches the growing size of the target file and updates a progress bar using that information. The latter method saves you a PInvoke, but the former is probably a bit cleaner in the long run.
对于这类事情,我已经退回到 Shell32(或者是 ShellUI?我不再知道了)。 这为您提供了一个本机 Windows 对话框,用户习惯于在复制操作中看到该对话框。 我想它会取代您已经存在的对话框,因此它可能不是您的正确答案,但记住对于那些“紧要关头”的情况很有用。
是的,您必须引用 Microsoft.VisualBasic 程序集。 我已经喜欢这个程序集了。
For these sorts of things I have fallen back to Shell32 (or is it ShellUI? I don't know anymore). This gives you a native Windows dialog that users are used to seeing for copying operations. I guess it would replace your already existing dialog so it may not be the right answer for you, but it is useful to remember for those "in a pinch" scenarios.
Yes, you must reference the Microsoft.VisualBasic assembly. I've grown to love this assembly.
感谢@Gasper 和@Dennis 指出CopyFileEx 方法。
我用中止复制扩展了丹尼斯的答案
客户端可以创建 XCopy 类的对象并调用复制/中止方法。
Thanks to @Gasper and @Dennis for pointing out CopyFileEx method.
I have extended dennis answer with abort copy
The clients can create an object of XCopy class and call copy/abort method .
如果有人仍然像我一样遇到这个问题(10年后!),我已经创建了一个围绕 CopyFileEx 和 MoveFileWithProgress 函数(如此处的一些答案)的包装器,其中包含一些额外的、有用的功能(例如异步、访问权限检查、字节格式化、复制目录...)
在这里检查 -
GitHub 和
Nuget
If someone still stumbles into this problem (10 years later!) as I did, I have created a wrapper around CopyFileEx and MoveFileWithProgress functions (as some of the answers here) with some extra, useful functionality (such as async, access rights check, formatting of bytes, copying directories...)
Check it here -
GitHub and
Nuget