3 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
5 using System.Collections.Generic;
6 using System.Diagnostics;
9 using System.Threading;
10 using SiliconStudio.Core.Diagnostics;
12 namespace SiliconStudio.Core.IO
14 public partial class DirectoryWatcher
16 private readonly Dictionary<string, DirectoryWatcherItem> watchers =
new Dictionary<string, DirectoryWatcherItem>(StringComparer.InvariantCultureIgnoreCase);
18 private void InitializeInternal()
20 watcherCheckThread =
new Thread(SafeAction.Wrap(RunCheckWatcher)) { IsBackground =
true, Name =
"RunCheckWatcher thread" };
21 watcherCheckThread.Start();
24 private void DisposeInternal()
26 foreach (var watcher
in watchers.Values)
28 if (watcher.Watcher != null)
30 DisposeNativeWatcher(watcher.Watcher);
32 watcher.Watcher = null;
37 private List<string> GetTrackedDirectoriesInternal()
39 List<string> directories;
42 directories = ListTrackedDirectories().Select(pair => pair.Key).ToList();
48 private void TrackInternal(
string path)
50 var info = GetDirectoryInfoFromPath(path);
62 private void UnTrackInternal(
string path)
64 var info = GetDirectoryInfoFromPath(path);
72 DirectoryWatcherItem watcher;
73 if (!watchers.TryGetValue(info.FullName, out watcher))
78 UnTrack(watcher,
true);
83 private void RunCheckWatcher()
90 Thread.Sleep(SleepBetweenWatcherCheck);
94 var list = ListTrackedDirectories().ToList();
95 foreach (var watcherKeyPath
in list)
97 if (!watcherKeyPath.Value.IsPathExist())
99 UnTrack(watcherKeyPath.Value,
true);
100 OnModified(
this,
new FileEvent(
FileEventChangeType.Deleted, Path.GetFileName(watcherKeyPath.Value.Path), watcherKeyPath.Value.Path));
105 if (!ListTrackedDirectories().
Any())
114 Trace.WriteLine(string.Format(
"Unexpected end of thread {0}", ex));
121 return watchers.Where(pair => pair.Value.Watcher != null);
124 private DirectoryInfo GetDirectoryInfoFromPath(
string path)
126 if (path == null)
throw new ArgumentNullException(
"path");
128 path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, path));
132 if (
File.Exists(path))
134 path = Path.GetDirectoryName(path);
137 if (path != null && Directory.Exists(path))
139 info =
new DirectoryInfo(path.ToLower());
151 foreach (var directoryInfo
in directories)
153 DirectoryWatcherItem watcher;
154 if (watchers.TryGetValue(directoryInfo.FullName, out watcher))
156 yield
return watcher;
163 return ListTracked(watcher.ListChildrenDirectories());
168 return ListTracked(directories).Count(watcher => watcher.Watcher != null);
171 private DirectoryWatcherItem Track(DirectoryInfo info,
bool watcherNode)
173 DirectoryWatcherItem watcher;
174 if (watchers.TryGetValue(info.FullName, out watcher))
176 watcher.TrackCount++;
180 var parent = info.Parent != null ? Track(info.Parent,
false) : null;
182 if (parent != null && watcherNode)
184 if (parent.Watcher != null)
189 var childrenDirectoryList = parent.ListChildrenDirectories().ToList();
190 var countTracked = CountTracked(childrenDirectoryList);
192 var newCount = (countTracked + 1);
193 if (newCount == childrenDirectoryList.Count && newCount > 1)
195 UnTrack(parent,
false);
196 parent.Watcher = CreateFileSystemWatcher(parent.Path);
201 watcher =
new DirectoryWatcherItem(info) { Parent = parent };
204 watcher.Watcher = CreateFileSystemWatcher(watcher.Path);
206 watchers.Add(watcher.Path, watcher);
208 watcher.TrackCount++;
212 private void UnTrack(DirectoryWatcherItem watcher,
bool removeWatcherFromGlobals)
214 foreach (var child
in ListTrackedChildren(watcher))
216 UnTrack(child,
true);
219 watcher.TrackCount--;
221 if (watcher.TrackCount == 0)
223 if (watcher.Watcher != null)
225 DisposeNativeWatcher(watcher.Watcher);
226 watcher.Watcher = null;
229 watcher.Parent = null;
231 if (removeWatcherFromGlobals)
233 watchers.Remove(watcher.Path);
238 private void DisposeNativeWatcher(FileSystemWatcher watcher)
241 watcher.EnableRaisingEvents =
false;
242 watcher.Changed -= OnModified;
243 watcher.Created -= OnModified;
244 watcher.Deleted -= OnModified;
245 watcher.Renamed -= OnModified;
246 watcher.Error -= WatcherOnError;
251 protected FileSystemWatcher CreateFileSystemWatcher(
string directory)
254 var watcher =
new FileSystemWatcher()
257 NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
259 IncludeSubdirectories =
true
264 watcher.Changed += OnModified;
265 watcher.Created += OnModified;
266 watcher.Deleted += OnModified;
267 watcher.Renamed += OnModified;
268 watcher.Error += WatcherOnError;
271 watcher.EnableRaisingEvents =
true;
277 private void WatcherOnError(
object sender, ErrorEventArgs errorEventArgs)
284 var watcher = watchers.Values.FirstOrDefault(item => item.Watcher == sender);
288 UnTrack(watcher,
true);
294 Trace.WriteLine(string.Format(
"Unexpected exception in WatcherOnError: {0}", ex));
298 private void OnModified(
object sender, FileSystemEventArgs e)
302 DirectoryWatcherItem watcher;
303 if (e.ChangeType == WatcherChangeTypes.Deleted && watchers.TryGetValue(e.FullPath, out watcher))
305 UnTrack(watcher,
true);
316 [DebuggerDisplay(
"Active: {IsActive}, Path: {Path}")]
317 private sealed
class DirectoryWatcherItem
319 public DirectoryWatcherItem(DirectoryInfo path)
321 Path = path.FullName.ToLower();
324 public DirectoryWatcherItem Parent;
326 public string Path {
get;
private set; }
328 public bool IsPathExist()
330 return Directory.Exists(Path);
333 public int TrackCount {
get; set; }
335 public FileSystemWatcher Watcher {
get; set; }
339 var info =
new DirectoryInfo(Path);
344 return info.EnumerateDirectories();
351 return Enumerable.Empty<DirectoryInfo>();
354 private bool IsActive
358 return Watcher != null;
Let the emitter choose the style.
Data reference has been set to a new value by the user. It will be changed to Loaded as soon as it ha...
FileEventChangeType
Change type of file used by FileEvent and DirectoryWatcher.