I have a C# application and I want to copy a file to a new location. Some times I need to overwrite an existing file. when this happens I receive a System.IO.IOException. I want to recover from a Sharing violation but how do I determine that IOException was returned because the destination file is in use rather then some other reason? I could look for the "The process cannot access the file because it is being used by another process." message... But I don't like that idea.
This was the solution I came up with.
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;
}
}
As other answers have stated, you need to get the HResult of the error and check it. An HResult of 32 is a sharing violation.
In .NET 4.5, the IOException
has a public HResult
property, so you can just do as follows:
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
}
}
In earlier versions of .NET, however, you need to get the HResult
by calling Marshal.GetHRForException(Exception)
, so the similar code would be:
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 allows you to use this syntax to catch only a sharing violation with a when
clause:
try
{
// do file IO here
}
catch (IOException e) when (e.HResult == 32) // 32 = Sharing violation
{
// Recovery logic goes here
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With