简体   繁体   English

C# - File.Move - 找不到文件

[英]C# - File.Move - Could not find file

i have a strange problem with File.Move method. File.Move 方法有一个奇怪的问题。 Generally I have a service, that monitors for new files appearing on remote share and once they do it changes its extension via "ren" cmd function and calls other service.一般来说,我有一个服务,它监视远程共享上出现的新文件,一旦他们这样做,它就会通过“ren”cmd function 更改其扩展名并调用其他服务。 This other service is then using File.Move to change the extension of the file once again.然后,此其他服务使用 File.Move 再次更改文件的扩展名。 The problem is that from time to time the second service fails and returns error "Could not find file..." from System.IO.File.InternalMove, while the file is already there.问题是有时第二个服务失败并从 System.IO.File.InternalMove 返回错误“找不到文件...”,而文件已经存在。

Initially I thought that it may be issue with network connection, but I have a feeling that it happens to often to be caused by network problems.起初我以为可能是网络连接的问题,但我感觉它经常是由网络问题引起的。

Next I started digging into .net source code and found something interesting:接下来我开始深入研究 .net 源代码,发现了一些有趣的东西:

        if (!InternalExists(fullSourceFileName))
             __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName);
        
        if (!Win32Native.MoveFile(fullSourceFileName, fullDestFileName))
        {
            __Error.WinIOError();
        }

This is part of File.InternalMove method which, from my understanding, is returning an "Could not find file..." error.这是 File.InternalMove 方法的一部分,据我了解,该方法返回“找不到文件...”错误。 In short InternalExists method is checking if file exists by checking the Marshal.GetLastWin32Error() error and later verifing attributes on file.简而言之,InternalExists 方法是通过检查 Marshal.GetLastWin32Error() 错误和稍后验证文件上的属性来检查文件是否存在。

Also what is strange is that it seems that this method is using "hack" of some sort (don't know if it is related to my problem, but it is worrying):另外奇怪的是,这种方法似乎使用了某种“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);
            }

Now the interestring part:) Class FileInfo also allows to rename files via MoveTo() method.现在有趣的部分:) Class FileInfo 还允许通过 MoveTo() 方法重命名文件。 In this method the "moving" part is following:在这种方法中,“移动”部分如下:

 if (!Win32Native.MoveFile(FullPath, fullDestFileName))
            __Error.WinIOError();

It is the same as in File class, but it lacks the "InternalExists" verification, so at a glance it looks like it should resolve my problem, but I am little worried about this missing check.它与文件 class 中的相同,但它缺少“InternalExists”验证,所以乍一看它应该可以解决我的问题,但我有点担心这个缺失的检查。

Does anybody knows why it is implemented like this and if I can use FileInfo.MoveTo method?有谁知道为什么它是这样实现的,如果我可以使用 FileInfo.MoveTo 方法? Also if you have any ideas on the cause of the problem, then please share it.另外,如果您对问题的原因有任何想法,请分享。 Currently I am quessing that when first service is calling "ren" cmd program, the new file isn't fully renamed yet, which causes File.Move method to fail, but I have to yet verify it.目前我正在质疑,当第一个服务调用“ren”cmd 程序时,新文件还没有完全重命名,这导致 File.Move 方法失败,但我还需要验证它。

I'm guessing the error is actually a permissions issue, or possibly a locked file, and that the error returned by InternalExists isn't actually ERROR_FILE_NOT_FOUND , as no check is made on it.我猜这个错误实际上是一个权限问题,或者可能是一个锁定的文件,并且InternalExists返回的错误实际上不是ERROR_FILE_NOT_FOUND ,因为没有对其进行检查。

Therefore it's a bug that the correct error is not thrown.因此,没有抛出正确的错误是一个错误。

Why the Exists check needs to be there is unclear anyway: if it's not there you will get an error anyway when calling MoveFile .无论如何,为什么需要存在 Exists 检查尚不清楚:如果不存在,则在调用MoveFile时无论如何都会出错。

I suggest you file this as a bug on the GitHub repo.我建议你在 GitHub repo 上将此作为一个错误提交。 I think it's unlikely to get fixed, but at least it will be documented.我认为它不太可能得到修复,但至少它会被记录在案。 If it gets closed as Won't fix you may want to file a pull request on the documentation noting this.如果它因Won't fix而关闭,您可能需要在文档中提交拉取请求,并注明这一点。

Note that the current code is actually the following, which implements the same thing in a slightly different way.请注意, 当前代码实际上是以下代码,它以稍微不同的方式实现相同的东西。

            if (!FileSystem.FileExists(fullSourceFileName))
            {
                throw new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, fullSourceFileName), fullSourceFileName);
            }

            FileSystem.MoveFile(fullSourceFileName, fullDestFileName, overwrite);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM