Dan Schubel
Dan Schubel

Reputation: 279

What is the best way to lock a file to prevent multiple users from accessing it

I have a windows form app in which users can open, create and save xml files. Files are typically saved to a network folder. I need to make sure a given file can only be opened by one user at a time. The xml file is loaded into a tree control and is saved frequently during a session. (almost any time a tree node is clicked) I'm opening the file like this:

FileStream fs = new FileStream(m_Filename, FileMode.Open);
XmlReader reader = new XmlTextReader(fs);
XmlSerializer deserializer = new XmlSerializer(typeof(BaseBoardTest));
m_TestNodes = (BaseBoardTest)deserializer.Deserialize(reader);
fs.Close();

Saving like this:

TextWriter writer = new StreamWriter(filename);
XmlSerializer serializer = new XmlSerializer(typeof(BaseBoardTest));
serializer.Serialize(writer, m_TestNodes);
writer.Close();

I'd like to display a message stating which user/computer name has the file open if another user tries to open it or overwrite it via a save as. I am considering creating a lock file when a file is opened. Is there a better way to handle this?

Upvotes: 3

Views: 2844

Answers (4)

Joshua
Joshua

Reputation: 4139

If you are wanting to prevent users from opening the file when it's been opened by another user, you will need the FileShare.None enum.

You should replace

new FileStream(m_Filename, FileMode.Open);

with

new FileStream(m_Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None)

More information on FileShare.None can be found here: http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx

Note: Be sure to catch any exceptions raised when attempting to open the file. If one user has opened the file, then any subsequent request to open the file will raise a System.IO.IOException until the file has been closed.

Upvotes: 1

chridam
chridam

Reputation: 103365

You could handle that by only locking write access, thereby allowing others to still read the file:

using (FileStream fs = new FileStream(m_Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
   XmlReader reader = new XmlTextReader(fs);
   XmlSerializer deserializer = new XmlSerializer(typeof(BaseBoardTest));
   m_TestNodes = (BaseBoardTest)deserializer.Deserialize(reader);
   fs.Close();

   TextWriter writer = new StreamWriter(filename);
   XmlSerializer serializer = new XmlSerializer(typeof(BaseBoardTest));
   serializer.Serialize(writer, m_TestNodes);
   writer.Close();
}

Upvotes: 0

Marcus
Marcus

Reputation: 8669

This is a snippet from a synchronized logger functionality. It is unaccessible until the write has completed and is thread safe.

internal class WriteToLockedFile
    {
        internal static string Uri { get; set ; }
        private static readonly object _syncObject = new object();

        public static void WriteToFile(string logMessage)
        {
            using (var stream = TextWriter.Synchronized( File.AppendText(Uri)))
            {
                lock (_syncObject) 
                {
                    stream.WriteLine(" {0}", logMessage); stream.Flush(); 
                }
            }
        }
    }

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174309

A lock file will be the only way if you want to display additional information.

Upvotes: 2

Related Questions