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

时间:2009-01-08 21:07:51

标签: c# vb.net .net-3.5

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

4 个答案:

答案 0 :(得分: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 :(得分:5)

这个article解释了如何获取异常HRESULT,以便您可以确定错误原因。

答案 2 :(得分:2)

正如其他答案所述,您需要获取错误的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
    }
}

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

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

答案 3 :(得分:-2)

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

抓住(例外)                 {                 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