diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj
index adddde88..4eb072df 100644
--- a/MinecraftClient/MinecraftClient.csproj
+++ b/MinecraftClient/MinecraftClient.csproj
@@ -97,6 +97,7 @@
+
diff --git a/MinecraftClient/Protocol/Session/SessionCache.cs b/MinecraftClient/Protocol/Session/SessionCache.cs
index b388018c..279e4375 100644
--- a/MinecraftClient/Protocol/Session/SessionCache.cs
+++ b/MinecraftClient/Protocol/Session/SessionCache.cs
@@ -23,8 +23,8 @@ namespace MinecraftClient.Protocol.Session
"launcher_profiles.json"
);
+ private static SessionFileMonitor cachemonitor;
private static Dictionary sessions = new Dictionary();
- private static FileSystemWatcher cachemonitor = new FileSystemWatcher();
private static Timer updatetimer = new Timer(100);
private static List> pendingadds = new List>();
private static BinaryFormatter formatter = new BinaryFormatter();
@@ -81,15 +81,8 @@ namespace MinecraftClient.Protocol.Session
/// TRUE if session tokens are seeded from file
public static bool InitializeDiskCache()
{
- cachemonitor.Path = AppDomain.CurrentDomain.BaseDirectory;
- cachemonitor.IncludeSubdirectories = false;
- cachemonitor.Filter = SessionCacheFilePlaintext;
- cachemonitor.NotifyFilter = NotifyFilters.LastWrite;
- cachemonitor.Changed += new FileSystemEventHandler(OnChanged);
- cachemonitor.EnableRaisingEvents = true;
-
+ cachemonitor = new SessionFileMonitor(AppDomain.CurrentDomain.BaseDirectory, SessionCacheFilePlaintext, new FileSystemEventHandler(OnChanged));
updatetimer.Elapsed += HandlePending;
-
return LoadFromDisk();
}
diff --git a/MinecraftClient/Protocol/Session/SessionFileMonitor.cs b/MinecraftClient/Protocol/Session/SessionFileMonitor.cs
new file mode 100644
index 00000000..00cedf77
--- /dev/null
+++ b/MinecraftClient/Protocol/Session/SessionFileMonitor.cs
@@ -0,0 +1,83 @@
+using System;
+using System.IO;
+using System.Threading;
+
+namespace MinecraftClient.Protocol.Session
+{
+ ///
+ /// Monitor session file changes on disk
+ ///
+ class SessionFileMonitor
+ {
+ private FileSystemWatcher monitor;
+ private Thread polling;
+
+ ///
+ /// Create a new SessionFileMonitor and start monitoring
+ ///
+ /// Folder to monitor
+ /// Filename inside folder
+ /// Callback for file changes
+ public SessionFileMonitor(string folder, string filename, FileSystemEventHandler handler)
+ {
+ if (Settings.DebugMessages)
+ ConsoleIO.WriteLineFormatted("§8Initializing disk session cache using FileSystemWatcher");
+
+ try
+ {
+ monitor = new FileSystemWatcher();
+ monitor.Path = folder;
+ monitor.IncludeSubdirectories = false;
+ monitor.Filter = filename;
+ monitor.NotifyFilter = NotifyFilters.LastWrite;
+ monitor.Changed += handler;
+ monitor.EnableRaisingEvents = true;
+ }
+ catch
+ {
+ if (Settings.DebugMessages)
+ ConsoleIO.WriteLineFormatted("§8Failed to initialize FileSystemWatcher, retrying using Polling");
+
+ polling = new Thread(() => PollingThread(folder, filename, handler));
+ polling.Start();
+ }
+ }
+
+ ///
+ /// Fallback polling thread for use when operating system does not support FileSystemWatcher
+ ///
+ /// Folder to monitor
+ /// File name to monitor
+ /// Callback when file changes
+ private void PollingThread(string folder, string filename, FileSystemEventHandler handler)
+ {
+ string filePath = String.Concat(folder, Path.DirectorySeparatorChar, filename);
+ DateTime lastWrite = GetLastWrite(filePath);
+ while (true)
+ {
+ Thread.Sleep(5000);
+ DateTime lastWriteNew = GetLastWrite(filePath);
+ if (lastWriteNew != lastWrite)
+ {
+ lastWrite = lastWriteNew;
+ handler(this, new FileSystemEventArgs(WatcherChangeTypes.Changed, folder, filename));
+ }
+ }
+ }
+
+ ///
+ /// Get last write for a given file
+ ///
+ /// File path to get last write from
+ /// Last write time, or DateTime.MinValue if the file does not exist
+ private DateTime GetLastWrite(string path)
+ {
+ FileInfo fileInfo = new FileInfo(path);
+ if (fileInfo.Exists)
+ {
+ return fileInfo.LastWriteTime;
+ }
+ else return DateTime.MinValue;
+ }
+ }
+}