2009-01-08 60 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 
}