C# 在文件可用时立即移动文件
我需要完成以下任务:
尝试移动文件。如果文件被锁定,则计划在其可用后立即移动。
我正在使用 File.Move 这对于我的程序来说已经足够了。现在的问题是:
1)我找不到一个好的方法来检查我需要移动的文件是否被锁定。我正在捕获 System.IO.IOException 但阅读周围的其他帖子我发现相同的异常也可能因不同的原因而引发。
2) 确定文件何时解锁。实现此目的的一种方法可能是使用计时器/线程并检查计划的文件(假设每 30 秒一次)并尝试移动它们。但我希望有更好的方法使用 FileSystemWatcher。
这是一个 .net 3.5 winforms 应用程序。如有任何意见/建议,我们将不胜感激。感谢您的关注。
I need to accomplish the following task:
Attempt to move a file. If file is locked schedule for moving as soon as it becomes available.
I am using File.Move which is sufficient for my program. Now the problems are that:
1) I can't find a good way to check if the file I need to move is locked. I am catching System.IO.IOException but reading other posts around I discovered that the same exception may be thrown for different reasons as well.
2) Determining when the file gets unlocked. One way of doing this is probably using a timer/thread and checking the scheduled files lets say every 30 seconds and attempting to move them. But I hope there is a better way using FileSystemWatcher.
This is a .net 3.5 winforms application. Any comments/suggestions are appreciated. Thanks for attention.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您确实应该尝试捕获 IOException。使用 Marshal.GetHRForException 检查异常原因。
通知并不可靠。在执行 File.Move 之前,另一个进程可能会再次锁定文件。
You should really just try and catch an IOException. Use Marshal.GetHRForException to check for the cause of the exception.
A notification would not be reliable. Another process might lock the file again before File.Move is executed.
一种可能的替代方法是使用
MoveFileEx
带有MOVEFILE_DELAY_UNTIL_REBOOT
标志。如果您现在无权移动该文件,则可以安排在下次重新启动时移动该文件,此时保证可以访问该文件(移动发生在启动序列的早期)。根据您的特定应用程序,除了移动计划之外,您还可以通知用户需要重新启动并自行启动重新启动。
One possible alternative is by using
MoveFileEx
with aMOVEFILE_DELAY_UNTIL_REBOOT
flag. If you don't have access to move the file right now, you can schedule it to be moved on the next reboot when it's guaranteed to be accessible (the moving happens very early in the boot sequence).Depending on your specific application, you could inform the user a reboot is necessary and initiate the reboot yourself in addition to the moving scheduling.
很简单:
It's simple:
这并不是特定于您的问题,但通常您始终需要为此类操作保留“尝试并优雅地处理失败”的操作模式。
这是因为,无论您的“检测文件可用”机制有多聪明,在您检测到文件可用和移动它之间总会有一段时间,在这段时间内其他人可能会弄乱文件。
This is not specific to your problem, but generally you will always need to retain the 'try it and gracefully deal with a failure' mode of operation for this sort of action.
That's because however clever your 'detect that the file is available' mechanism is, there will always be some amount of time between you detecting that the file is available and moving it, and in that time someone else might mess with the file.
计划的异常重试(可能会增加延迟 - 在一定程度上)可能是实现此目的的最简单方法(您的 (2) )。
为了正确地做到这一点,您将必须下降到系统级别(使用内核代码)挂钩来捕获文件关闭事件 - 该事件有其自己的特性。这是一项艰巨的工作 - 比计划的重试方法复杂几个数量级。这取决于您和您的应用程序案例来做出决定,但我不知道这之间有什么有效的方法。
The scheduled retry on exception (probably increasing delays - up to a point) is probably the simplest way to achieve this (your (2) ).
To do it properly you're going to have to drop to system level (with Kernel code) hooks to trap the file close event - which has its own idiosynchrases. It's a big job - several orders of magnitude more complex than the scheduled retry method. It's up to you and your application case to make that call, but I don't know of anything effective in between.
非常老的问题,但是谷歌引导我来到这里,所以当我找到更好的答案时,我决定发布它:
我发现了一个很好的代码 在 dotnet CLI 存储库中:
还有一个仅针对
IOException
的方法。这是使用示例 :总体而言,这个存储库包含许多关于文件操作和安装/删除逻辑的有趣想法,例如
TransactionalAction
,因此我建议您查看它。不幸的是,这些函数不能作为 NuGet 包提供。Very old question, but google led me here, so when I found a better answer I decided to post it:
There's a nice code I found in the dotnet CLI repo:
There is also a method for just
IOException
. Here's the usage example:Overall, this repo contains a lot of interesting ideas for file manipulations and installation/removal logic, like
TransactionalAction
, so I recommend it for reviewing. Unfortunately, these functions are not available as NuGet package.看一下 FileSystemWatcher。
http://msdn.microsoft.com /en-us/library/system.io.filesystemwatcher(VS.90).aspx
Have a look at the FileSystemWatcher.
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(VS.90).aspx