2009-01-08 56 views
5

我有一個C#應用程序,我想將一個文件複製到一個新的位置。有時我需要覆蓋現有的文件。 發生這種情況時,我收到一個System.IO.IOException。我想從共享衝突中恢復,但是如何確定由於目標文件正在使用而不是其他原因而返回IOException?我可以查找「該進程無法訪問該文件,因爲它正在被另一個進程使用」。消息......但我不喜歡那個想法。如何確定是否由於共享衝突而拋出IOException?

回答

5

article說明如何獲取異常HRESULT,以便您可以確定錯誤原因。

+0

我正要表明:) – 2009-01-08 21:37:40

+0

沒有,IOException異常使用HRESULT COR_E_IO具有恆定值0x80131620 [請參閱IOException類](https://msdn.microsoft.com/en-us/library/system.io.ioexception(v = vs.110).aspx)。 – tibx 2018-02-19 14:14:36

+0

但實際上似乎IOException類的HResult屬性具有真正的HRSEULT錯誤原因... – tibx 2018-02-19 14:22:16

-1

查找,你可以處理,例如明確的錯誤代碼:

趕上(例外U) { 如果(((SocketException)U).ErrorCode == 10035) ...

到這裏看看: http://msdn.microsoft.com/en-us/library/ms681391(VS.85).aspx

錯誤代碼,如:

ERROR_SHARING_VIOLATION - 32 - 爲0x20

ERROR_ACCESS_DENIED = 5 - 爲0x5

ERROR_FILE_NOT_FOUND - 2 - 0×2

+0

從IOException轉換到SocketException將如何成功? – 2009-01-08 21:53:48

7

這是我想出瞭解決方案。

private void RobustMoveFile(System.IO.DirectoryInfo destinationDirectory, System.IO.FileInfo sourceFile, Boolean retryMove) 
       { 
        try 
        { 
         string DestinationFile = Path.Combine(destinationDirectory.FullName, sourceFile.Name); 
         if (File.Exists(DestinationFile)) 
          sourceFile.Replace(DestinationFile, DestinationFile + "Back", true); 
         else 
         { 
          sourceFile.CopyTo(DestinationFile, true); 
          sourceFile.Delete(); 
         } 
        } 
        catch (System.IO.IOException IOEx) 
        { 
         int HResult = System.Runtime.InteropServices.Marshal.GetHRForException(IOEx);   
         const int SharingViolation = 32; 
         if ((HResult & 0xFFFF) == SharingViolation && retryMove) 
          RobustMoveFile(destinationDirectory, sourceFile, false); 
         throw; 
        } 
       } 
1

正如其他答案所述,您需要獲取錯誤的HResult並檢查它。 32的HResult是共享違規。

.NET 4.5,該IOException具有公共HResult屬性,因此你可以做如下:

try 
{ 
    // do file IO here 
} 
catch (IOException e) 
{ 
    if (e.HResult == 32) // 32 = Sharing violation 
    { 
     // Recovery logic goes here 
    } 
    else 
    { 
     throw; // didn't need to catch this 
    } 
} 

早期版本的.NET,但是,你需要得到HResult通過調用Marshal.GetHRForException(Exception),所以類似的代碼將是:

try 
{ 
    // do file IO here 
} 
catch (IOException e) 
{ 
    int HResult = System.Runtime.InteropServices.Marshal.GetHRForException(e) 
    if (HResult == 32) // 32 = Sharing violation 
    { 
     // Recovery logic goes here 
    } 
    else 
    { 
     throw; // Or do whatever else here 
    } 
} 

的尚未公佈C#6.0意願,根據A C# 6.0 Language Preview,允許您使用此語法只捕獲共享衝突:

try 
{ 
    // do file IO here 
} 
catch (IOException e) 
    if (e.HResult == 32) // 32 = Sharing violation 
{ 
    // Recovery logic goes here 
}