如何确定是否因共享冲突而抛出IOException?

我有一个C#应用程序,我想将文件复制到一个新位置。 有时我需要覆盖现有文件。 当发生这种情况时,我收到一个System.IO.IOException。 我想从共享冲突中恢复但是如何确定是否返回了IOException,因为目标文件正在使用而不是其他原因? 我可以查找“进程无法访问该文件,因为它正被另一个进程使用”。 消息……但我不喜欢这个主意。

本文介绍如何获取exceptionHRESULT,以便您可以确定错误原因。

这是我提出的解决方案。

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; } } 

正如其他答案所述,您需要获取错误的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中,您需要通过调用Marshal.GetHRForException(Exception)来获取HResult ,因此类似的代码将是:

 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 } } 

根据AC#6.0语言预览 ,尚未发布的C#6.0将允许您使用此语法仅捕获共享冲突:

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

查找可以处理的显式错误代码,例如:

catch(Exception u){if(((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 – 0x2