【发布时间】:2010-09-30 08:53:03
【问题描述】:
我有一个 C# 应用程序,我想将一个文件复制到一个新位置。有时我需要覆盖现有文件。 发生这种情况时,我会收到 System.IO.IOException。我想从共享冲突中恢复,但是如何确定返回 IOException 是因为目标文件正在使用而不是其他原因?我可以查找“该进程无法访问该文件,因为它正在被另一个进程使用”。消息...但我不喜欢这个主意。
【问题讨论】:
我有一个 C# 应用程序,我想将一个文件复制到一个新位置。有时我需要覆盖现有文件。 发生这种情况时,我会收到 System.IO.IOException。我想从共享冲突中恢复,但是如何确定返回 IOException 是因为目标文件正在使用而不是其他原因?我可以查找“该进程无法访问该文件,因为它正在被另一个进程使用”。消息...但我不喜欢这个主意。
【问题讨论】:
这是我想出的解决方案。
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
}
}
C# 6.0 允许您使用此语法仅捕获带有 when 子句的共享冲突:
try
{
// do file IO here
}
catch (IOException e) when (e.HResult == 32) // 32 = Sharing violation
{
// Recovery logic goes here
}
【讨论】:
寻找您可以处理的显式错误代码,例如:
catch (例外 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
【讨论】: