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
- 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.
- Common Error Codes:
32
(ERROR_SHARING_VIOLATION): File is locked by another process.33
(ERROR_LOCK_VIOLATION): Part of the file is locked.
- 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
Method | Use Case |
---|---|
File.Open + FileShare.None | Best for checking exclusive locks. |
Error Code 32 Check | Accurately identifies sharing violations. |
Retry Logic | Handles temporary locks during file writes. |
By using these methods, you can reliably check if a file is in use in C#.