【发布时间】:2022-08-14 19:06:38
【问题描述】:
File.Move 方法有一个奇怪的问题。 通常我有一个服务,它监视远程共享上出现的新文件,一旦他们这样做,它就会通过 \"ren\" cmd 函数更改其扩展名并调用其他服务。然后,此其他服务正在使用 File.Move 再次更改文件的扩展名。问题是有时第二个服务失败并从 System.IO.File.InternalMove 返回错误“找不到文件...”,而文件已经存在。
起初我以为可能是网络连接的问题,但我感觉它经常是由网络问题引起的。
接下来我开始深入研究 .net 源代码,发现了一些有趣的东西:
if (!InternalExists(fullSourceFileName))
__Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName);
if (!Win32Native.MoveFile(fullSourceFileName, fullDestFileName))
{
__Error.WinIOError();
}
这是 File.InternalMove 方法的一部分,据我了解,该方法返回“找不到文件...”错误。简而言之,InternalExists 方法是通过检查 Marshal.GetLastWin32Error() 错误和稍后验证文件上的属性来检查文件是否存在。
另外奇怪的是,这种方法似乎使用了某种“hack”(不知道它是否与我的问题有关,但令人担忧):
// For floppy drives, normally the OS will pop up a dialog saying
// there is no disk in drive A:, please insert one. We don\'t want that.
// SetErrorMode will let us disable this, but we should set the error
// mode back, since this may have wide-ranging effects.
bool success = false;
int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
try {
success = Win32Native.GetFileAttributesEx(path, GetFileExInfoStandard, ref data);
}
finally {
Win32Native.SetErrorMode(oldMode);
}
现在有趣的部分:) FileInfo 类还允许通过 MoveTo() 方法重命名文件。 在这种方法中,“移动”部分如下:
if (!Win32Native.MoveFile(FullPath, fullDestFileName))
__Error.WinIOError();
它与 File 类中的相同,但缺少“InternalExists”验证,所以乍一看它应该可以解决我的问题,但我有点担心这个缺失的检查。
有谁知道为什么它是这样实现的,如果我可以使用 FileInfo.MoveTo 方法? 另外,如果您对问题的原因有任何想法,请分享。目前我正在质疑,当第一个服务调用 \"ren\" cmd 程序时,新文件还没有完全重命名,这导致 File.Move 方法失败,但我必须验证它。
-
我在尝试执行处理文件的程序时遇到了这样的问题。我发现不同的操作系统,主要是文件系统,对文件的处理方式不同。结果,该程序在我的 PC 和其他一些 PC 上运行,但不在其他 PC 上运行,主要是那些使用 Linux/ubuntu 操作系统的 PC。我没有解决方案,但给了你问题的线索。
-
您的服务是否异步和并发运行?
-
有点像,但是收到错误的服务应该一次处理一个文件。我检查了是否存在服务尝试同时处理同一文件两次的情况(例如,第一个更改扩展名,第二个由于文件实际上不再存在而出错)并且没有找到这种情况。同样对于我收到错误的每种情况,文件扩展名都没有改变。
-
我猜它实际上是权限问题,
InternalExists返回的错误实际上不是ERROR_FILE_NOT_FOUND。因此,没有抛出正确的错误是一个错误。为什么需要存在检查尚不清楚:如果它不存在,无论如何您都会收到错误。