Beispiel #1
0
            internal void Start()
            {
                // Make sure _fullPath doesn't contain a link or alias
                // since the OS will give back the actual, non link'd or alias'd paths
                _fullDirectory = Interop.Sys.RealPath(_fullDirectory);
                if (_fullDirectory == null)
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                Debug.Assert(string.IsNullOrEmpty(_fullDirectory) == false, "Watch directory is null or empty");

                // Normalize the _fullDirectory path to have a trailing slash
                if (_fullDirectory [_fullDirectory.Length - 1] != '/')
                {
                    _fullDirectory += "/";
                }

                // Get the path to watch and verify we created the CFStringRef
                SafeCreateHandle path = Interop.CoreFoundation.CFStringCreateWithCString(_fullDirectory);

                if (path.IsInvalid)
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Take the CFStringRef and put it into an array to pass to the EventStream
                SafeCreateHandle arrPaths = Interop.CoreFoundation.CFArrayCreate(new CFStringRef [1] {
                    path.DangerousGetHandle()
                }, (UIntPtr)1);

                if (arrPaths.IsInvalid)
                {
                    path.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Create the callback for the EventStream if it wasn't previously created for this instance.
                if (_callback == null)
                {
                    _callback = new Interop.EventStream.FSEventStreamCallback(FileSystemEventCallback);
                }

                // Make sure the OS file buffer(s) are fully flushed so we don't get events from cached I/O
                Interop.Sys.Sync();

                // Create the event stream for the path and tell the stream to watch for file system events.
                _eventStream = Interop.EventStream.FSEventStreamCreate(
                    _callback,
                    arrPaths,
                    Interop.EventStream.kFSEventStreamEventIdSinceNow,
                    0.0f,
                    EventStreamFlags);
                if (_eventStream.IsInvalid)
                {
                    arrPaths.Dispose();
                    path.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Create and start our watcher thread then wait for the thread to initialize and start
                // the RunLoop. We wait for that to prevent this function from returning before the RunLoop
                // has a chance to start so that any callers won't race with the background thread's initialization
                // and calling Stop, which would attempt to stop a RunLoop that hasn't started yet.
                var runLoopStarted = new ManualResetEventSlim();

                new Thread(WatchForFileSystemEventsThreadStart)
                {
                    IsBackground = true
                }.Start(runLoopStarted);
                runLoopStarted.Wait();
            }
Beispiel #2
0
 internal static extern void FSEventStreamStop(SafeEventStreamHandle streamRef);
Beispiel #3
0
 internal static extern void FSEventStreamUnscheduleFromRunLoop(
     SafeEventStreamHandle streamRef,
     CFRunLoopRef runLoop,
     SafeCreateHandle runLoopMode);
Beispiel #4
0
 internal static extern bool FSEventStreamStart(SafeEventStreamHandle streamRef);