How to check if a file is in use in C#?

To check if a file is in use in C#, you typically attempt to open the file with exclusive access. If this fails due to a sharing violation, the file is likely locked by another process. Below are detailed methods and examples to achieve this.

1. Using FileStream with Exception Handling

The most reliable way is to try opening the file and catch an IOException caused by a sharing violation (error code 32).

Example 1: Basic Check

using System.IO;
using System.Runtime.InteropServices;

public static bool IsFileInUse(string filePath)
{
    if (!File.Exists(filePath))
        return false;

    try
    {
        // Try to open the file with exclusive access
        using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
        {
            return false; // File is not in use
        }
    }
    catch (IOException ex)
    {
        // Check if the error is a sharing violation (0x80070020)
        int errorCode = Marshal.GetHRForException(ex) & 0xFFFF;
        return errorCode == 32; // 32 = ERROR_SHARING_VIOLATION
    }
    catch
    {
        return false; // Other errors (e.g., file not found, access denied)
    }
}

Usage:

string filePath = @"C:\Temp\example.txt";
if (IsFileInUse(filePath))
{
    Console.WriteLine("File is in use!");
}
else
{
    Console.WriteLine("File is available.");
}

2. Handling Edge Cases

Example 2: Differentiate Between Errors

Check the exact Win32 error code to distinguish sharing violations from other issues:

catch (IOException ex)
{
    if (ex.InnerException is System.ComponentModel.Win32Exception win32Ex)
    {
        // Check the native error code
        return win32Ex.NativeErrorCode == 32;
    }
    return false;
}

3. Alternative: Check File Accessibility

For non-exclusive checks, use FileShare modes to test read/write access.

Example 3: Check Read Access

public static bool CanReadFile(string filePath)
{
    try
    {
        using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            return true;
        }
    }
    catch
    {
        return false;
    }
}

Key Notes

  1. Limitations:
  • Race Conditions: The file may become locked/unlocked immediately after the check.
  • Permissions: Access denied errors (e.g., lack of permissions) are treated as “not in use.”
  • Network Files: May behave unpredictably due to latency or caching.
  1. Common Error Codes:
  • 32 (ERROR_SHARING_VIOLATION): File is locked by another process.
  • 33 (ERROR_LOCK_VIOLATION): Part of the file is locked.
  1. Performance: Avoid using this method in tight loops; it involves I/O operations.

Complete Example with Retry Logic

Retry the check if the file is temporarily locked (e.g., during a write operation):

public static bool IsFileInUseWithRetry(string filePath, int maxRetries = 3)
{
    int retries = 0;
    while (retries < maxRetries)
    {
        try
        {
            using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                return false;
            }
        }
        catch (IOException ex)
        {
            int errorCode = Marshal.GetHRForException(ex) & 0xFFFF;
            if (errorCode == 32)
            {
                retries++;
                Thread.Sleep(1000); // Wait 1 second before retrying
            }
            else
            {
                return false;
            }
        }
        catch
        {
            return false;
        }
    }
    return true; // Still locked after retries
}

Summary

MethodUse Case
File.Open + FileShare.NoneBest for checking exclusive locks.
Error Code 32 CheckAccurately identifies sharing violations.
Retry LogicHandles temporary locks during file writes.

By using these methods, you can reliably check if a file is in use in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *