BCarlson BCarlson - 2 months ago 17x
C# Question

How to remove a file lock

I have an service to move files from a working folder to backup folder. The folders are on a network share, so at times we will open a file, using something like notepad, to look at it. People are not (well, shouldn't) be editing, just looking.

When we try to move the file, I get permission denied. I'm looking for a way in C# to force remove a file lock, so the service can move the file to the backup folder.


You have to use P/Invoke. These are the functions you care about:

[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileEnum(string servername, string basepath, string username, int level, ref IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, IntPtr resume_handle);

[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileClose(string servername, int id);

[DllImport("Netapi32.dll", SetLastError = true)]
static extern int NetApiBufferFree(IntPtr buffer);

Here's some code similar to what I've used with success:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct FILE_INFO_3
    public int fi3_id;
    public int fi3_permission;
    public int fi3_num_locks;
    public string fi3_pathname;
    public string fi3_username;

private static FILE_INFO_3[] GetLockedFiles(string server, string path)
    const int MAX_PREFERRED_LENGTH = -1;

    int dwReadEntries;
    int dwTotalEntries;
    IntPtr pBuffer = IntPtr.Zero;
    FILE_INFO_3 pCurrent = new FILE_INFO_3();
    List<FILE_INFO_3> files = new List<FILE_INFO_3>();

    int dwStatus = NetFileEnum(server, path, null, 3, ref pBuffer, MAX_PREFERRED_LENGTH, out dwReadEntries, out dwTotalEntries, IntPtr.Zero);
    if (dwStatus == 0)
        for (int dwIndex = 0; dwIndex < dwReadEntries; dwIndex++)
            IntPtr iPtr = new IntPtr(pBuffer.ToInt32() + (dwIndex * Marshal.SizeOf(pCurrent)));
            pCurrent = (FILE_INFO_3)Marshal.PtrToStructure(iPtr, typeof(FILE_INFO_3));


    return files.ToArray();

static void Main(string[] args)
    FILE_INFO_3[] lockedFiles = GetLockedFiles("someservername", @"C:\somepath");

    foreach (FILE_INFO_3 lockedFile in lockedFiles)
        int dwStatus = NetFileClose(_serverName, lockedFile.fi3_id);
        // Check dwStatus for success here

EDIT: As noted by the OP in the comments below, when compiling as 64-bit, you need to use ToInt64 instead of ToInt32. More information can be found here.