簡體   English   中英

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

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

File.Move 方法有一個奇怪的問題。 一般來說,我有一個服務,它監視遠程共享上出現的新文件,一旦他們這樣做,它就會通過“ren”cmd function 更改其擴展名並調用其他服務。 然后,此其他服務使用 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);
            }

現在有趣的部分:) Class FileInfo 還允許通過 MoveTo() 方法重命名文件。 在這種方法中,“移動”部分如下:

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

它與文件 class 中的相同,但它缺少“InternalExists”驗證,所以乍一看它應該可以解決我的問題,但我有點擔心這個缺失的檢查。

有誰知道為什么它是這樣實現的,如果我可以使用 FileInfo.MoveTo 方法? 另外,如果您對問題的原因有任何想法,請分享。 目前我正在質疑,當第一個服務調用“ren”cmd 程序時,新文件還沒有完全重命名,這導致 File.Move 方法失敗,但我還需要驗證它。

我猜這個錯誤實際上是一個權限問題,或者可能是一個鎖定的文件,並且InternalExists返回的錯誤實際上不是ERROR_FILE_NOT_FOUND ,因為沒有對其進行檢查。

因此,沒有拋出正確的錯誤是一個錯誤。

無論如何,為什么需要存在 Exists 檢查尚不清楚:如果不存在,則在調用MoveFile時無論如何都會出錯。

我建議你在 GitHub repo 上將此作為一個錯誤提交。 我認為它不太可能得到修復,但至少它會被記錄在案。 如果它因Won't fix而關閉,您可能需要在文檔中提交拉取請求,並注明這一點。

請注意, 當前代碼實際上是以下代碼,它以稍微不同的方式實現相同的東西。

            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