Reputation: 279
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
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
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
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
Reputation: 174309
A lock file will be the only way if you want to display additional information.
Upvotes: 2