File lock

P

pgdown

Hi,

I have several processes accessing files from one folder, but only
one process should ever access each file. Once one process has the
file, no other process should be allowed to access it, even after the
first process is finished with it, except in the case where the first
process crashes. In pseudo code..

* Open file with exclusive lock
* Process file - failure will throw exception, skipping 'Remove
file' step below
* Close file and unlock
* Remove file - to clean up, but also to prevent other processes now
accessing the file

...So far I cannot think of a way of doing this, taking into account
pathological cases like the file being accessed between 'Close file
and unlock' and 'Remove file'. The closest I've come however is to use
File.Open(.. FileShare.Delete), so I can move the 'Remove file' above
the 'Close file and unlock', but then there the problem that someone
could come along and delete the file mid-processing.

Is there a possible solution in .NET? A way to keep the file locked
from other processes, but allow full access in the current, or an
atomic Close and Delete operation. It also needs to work across a
Windows file shared network using the UNC

Thank you,
Kind regards,
Eliott
 
M

Morten Wennevik [C# MVP]

Hi Elliot,

Try experimenting with a lock file and have each process check for the existance of a <Filename>.lock which would indicate that even though the file may be accessible, it should not be accessed. Once the file has been removed, remove the lock file as well.
 
M

MRe

Morten Wennevik said:
Hi Elliot,

Thank you for the response Morten Wennevik,
Try experimenting with a lock file and have each process check for the
existance of a <Filename>.lock which would indicate that even though the
file may be accessible, it should not be accessed. Once the file has been
removed, remove the lock file as well.

This is almost perfect, except that if the process that gains access to
the file crashes mid-processing, <Filename>.lock will not have a chance to
be deleted. Then the file would remain locked until a user deleted the .lock
manually.

I almost get it to work with File.Open(.., FileShare.Delete) because I can
delete the file while it's still locked and not crashed, plus, if the
program does crash, the OS takes care of the unlocking the file (only
problem is that someone could come along and delete the file
mid-processing).

If it was possible in .NET to create the .lock file so that it
automatically deleted itself when it was closed (like Win32's CreateFile(..,
FILE_FLAG_DELETE_ON_CLOSE); ) then this would work great.

Thanks again,
Kind regards,
Eliott
 
M

MRe

Darn it, sorry for the double-post of 'File lock'. Posted through Google and
it didn't show up after a day, so I thought it must have failed

Kind regards,
Eliott
 
M

Morten Wennevik [C# MVP]

Thank you for the response Morten Wennevik,


This is almost perfect, except that if the process that gains accessto
the file crashes mid-processing, <Filename>.lock will not have a chance to
be deleted. Then the file would remain locked until a user deleted the.lock
manually.

I almost get it to work with File.Open(.., FileShare.Delete) becauseI can
delete the file while it's still locked and not crashed, plus, if the
program does crash, the OS takes care of the unlocking the file (only
problem is that someone could come along and delete the file
mid-processing).

If it was possible in .NET to create the .lock file so that it
automatically deleted itself when it was closed (like Win32's CreateFile(..,
FILE_FLAG_DELETE_ON_CLOSE); ) then this would work great.

Thanks again,
Kind regards,
Eliott

Well, if you can do it in Win32, you can probably do it in .Net using pinvoke (see www.pinvoke.net)

In case of FILE_FLAG_DELETE_ON_CLOSE I did I quick test and the code below may be what you need. It will create a lock file when a winform loads and the lock file vanishes when the form is closed.

protected override void OnLoad(EventArgs e)
{
IntPtr hFile = Win32.CreateFile(
"C:\\Test.lock",
Win32.GENERIC_READ,
0,
IntPtr.Zero,
Win32.CREATE_NEW,
Win32.FILE_FLAG_DELETE_ON_CLOSE,
IntPtr.Zero);
}

class Win32
{
//DesiredAccess
public const UInt32 GENERIC_READ = 0x80000000;
public const UInt32 GENERIC_WRITE = 0x40000000;

//ShareMode
public const UInt32 FILE_SHARE_READ = 0x00000001;
public const UInt32 FILE_SHARE_WRITE = 0x00000002;

//CreationDisposition
public const UInt32 CREATE_NEW = 1;
public const UInt32 CREATE_ALWAYS = 2;
public const UInt32 OPEN_EXISTING = 3;
public const UInt32 OPEN_ALWAYS = 4;
public const UInt32 TRUNCATE_EXISTING = 5;

public const UInt32 FILE_FLAG_DELETE_ON_CLOSE = 0x04000000;

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
String lpFileName,
UInt32 dwDesiredAccess,
UInt32 dwShareMode,
IntPtr lpSecurityAttributes,
UInt32 dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile);
}
 
M

MRe

Hi Morten Wennevik,

Wow, thank you very much for all this code :) looks good. I will give it a
shot

Thank you again,
Kind regards,
Eliott

[..]
Try experimenting with a lock file and have each process check for the
existance of a <Filename>.lock which would indicate that even though the
file may be accessible, it should not be accessed. Once the file has
been
removed, remove the lock file as well.
[..]
If it was possible in .NET to create the .lock file so that it
automatically deleted itself when it was closed (like Win32's
CreateFile(..,
FILE_FLAG_DELETE_ON_CLOSE); ) then this would work great.
[..]

Well, if you can do it in Win32, you can probably do it in .Net using
pinvoke (see www.pinvoke.net)

In case of FILE_FLAG_DELETE_ON_CLOSE I did I quick test and the code below
may be what you need. It will create a lock file when a winform loads and
the lock file vanishes when the form is closed.

protected override void OnLoad(EventArgs e)
{
IntPtr hFile = Win32.CreateFile(
"C:\\Test.lock",
Win32.GENERIC_READ,
0,
IntPtr.Zero,
Win32.CREATE_NEW,
Win32.FILE_FLAG_DELETE_ON_CLOSE,
IntPtr.Zero);
}

class Win32
{
//DesiredAccess
public const UInt32 GENERIC_READ = 0x80000000;
public const UInt32 GENERIC_WRITE = 0x40000000;

//ShareMode
public const UInt32 FILE_SHARE_READ = 0x00000001;
public const UInt32 FILE_SHARE_WRITE = 0x00000002;

//CreationDisposition
public const UInt32 CREATE_NEW = 1;
public const UInt32 CREATE_ALWAYS = 2;
public const UInt32 OPEN_EXISTING = 3;
public const UInt32 OPEN_ALWAYS = 4;
public const UInt32 TRUNCATE_EXISTING = 5;

public const UInt32 FILE_FLAG_DELETE_ON_CLOSE = 0x04000000;

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
String lpFileName,
UInt32 dwDesiredAccess,
UInt32 dwShareMode,
IntPtr lpSecurityAttributes,
UInt32 dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top