1

EDIT: The problem has been resolved, see answer below.

I am having trouble accessing a FileSystemWatcher from another method.

EDIT: More code, as requested.

    public static void watch(string path)
    {
        FileSystemWatcher watcher = new FileSystemWatcher();

        watcher.Path = path;
        watcher.NotifyFilter = NotifyFilters.Attributes |
                       NotifyFilters.CreationTime |
                       NotifyFilters.DirectoryName |
                       NotifyFilters.FileName |
                       NotifyFilters.LastAccess |
                       NotifyFilters.LastWrite |
                       NotifyFilters.Security |
                       NotifyFilters.Size;
        watcher.Filter = "*.*";
        watcher.IncludeSubdirectories = true;
        watcher.Changed += new FileSystemEventHandler(OnChanged);
        watcher.Created += new FileSystemEventHandler(OnChanged);
        watcher.Deleted += new FileSystemEventHandler(OnChanged);
        watcher.Renamed += new RenamedEventHandler(OnChanged);
        watcher.EnableRaisingEvents = true;
    }

    private static void OnChanged(object sender, FileSystemEventArgs e)
    {
        // The reason for having this try block (and EnableRaisingEvents toggling) is to solve a known problem with FileSystemWatcher, in which the event is fired twice.

        try
        {
            MessageBox.Show("File changed.");

            watcher.EnableRaisingEvents = false; // Error: The name 'watcher' does not exist in the current context
        }
        finally
        {
            watcher.EnableRaisingEvents = true; //Error: The name 'watcher' does not exist in the current context
        }
    }

I want to change the EnableRaisingEvents property.

I can't do that because of the scope problem. Normally what I would do is declare the FileSystemWatcher somewhere with a bigger scope, but I can't do that here because a new one must be created every time I run the method.

So, how can I change the property of an object from a different method?

PS: I have searched around, and tried different things but ultimately nothing worked.

EDIT: Just to clarify, I MUST keep the FileSystemWatcher declaration INSIDE the method (as opposed to giving it a bigger scope, thus allowing it to be modified by another method). The reason for this is that I need a new one to be created every time I run the method.

bfl
  • 403
  • 2
  • 8
  • 1
    If there should be multiple watchers created from multiple `watch` calls, then how should `someOtherMethod` decide which one to use? – Servy May 06 '14 at 20:08
  • 1
    Is there a reason this can't just be passed as a method parameter? – drew_w May 06 '14 at 20:11
  • @Servy Sorry, I forgot to mention that "someOtherMethod" is actually an event handler, so it doesn't really matter who called it. – bfl May 06 '14 at 20:12
  • possible duplicate of [WPF - Cannot change a GUI property inside the OnChanged method (fired from FileSystemWatcher)](http://stackoverflow.com/questions/20575277/wpf-cannot-change-a-gui-property-inside-the-onchanged-method-fired-from-files) – Steve May 06 '14 at 20:13
  • @BeginnerForLife You didn't answer my question. How do you know which watcher to affect, when there could be several? Do you want to act on the most recent, all of them, is the event you're handling specific to one of those watchers, will there only be one active watcher at a time, even if there are several over the lifetime of the object? – Servy May 06 '14 at 20:47
  • 4
    Do you realize that your question has nothing to do with FileSystemWatcher? It's a general "how do I access a variable in two different methods" question. – John Saunders May 06 '14 at 20:51
  • @Steve No its a different question – bfl May 06 '14 at 21:55
  • @John Saunders Yes I realize that. The reason I chose that title was because I didn't know how else to phrase it. – bfl May 06 '14 at 22:03
  • @Servy The event will be the same for all FileSystemWatchers, and as drew_w pointed out if at some point I decide that I do need to know which FileSystemWatcher called it, I can just send it as a parameter. – bfl May 06 '14 at 22:03
  • Try the title I just edited. – John Saunders May 06 '14 at 22:03
  • You can't magically access a variable that's outside of its declared scope. Perhaps more code would provide some context. – Ryan Emerle May 06 '14 at 22:08
  • You need a lesson on [variable scope](http://msdn.microsoft.com/en-us/library/ms973875.aspx). – Icemanind May 06 '14 at 22:12
  • @icemanind I understand variable scope. The problem is I must declare the FileSystemWatcher **inside** the method, otherwise a new one won't be created every time I run it. – bfl May 06 '14 at 22:16
  • @RyanEmerle But shouldn't I be able to do something like `watch.watcher.EnableRaisingEvents = false` somehow? – bfl May 06 '14 at 22:19
  • 2
    `FileSystemWatcher watcher = new FileSystemWatcher(); watcher.WhateverEvent += eventHandler;`. Access the `sender` parameter to get back to your watcher. Be sure not to `Dispose` the watcher. – John Saunders May 06 '14 at 22:20
  • @JohnSaunders I can't do `sender.watch.watcher.EnableRaisingEvents = false` that would not work. – bfl May 06 '14 at 22:27
  • @BeginnerForLife No, you cannot access another method's scope. That's not how scope works. You don't need to declare the variable in the method in order for a new `FileSystemWatcher` to be created. You could declare it as a field, then assign a new `FileSystemWatcher` every time the method is called. If you need to keep track of all `FileSystemWatcher` objects, then use some kind of collection as the field. Again, without more detail as to what you're trying to do, it's hard to give you direction. – Ryan Emerle May 06 '14 at 22:38
  • @RyanEmerle I have added more code. If you could provide an edited version with the solution, please do. Thanks. – bfl May 06 '14 at 23:08

1 Answers1

2

In normal .NET eventing, there is a parameter called sender that has the object that sent the event. You can cast it to your type if you know the event has only one sender type anyway:

private static void OnChanged(object sender, FileSystemEventArgs e)
{
    var watcher = sender as FileSystemWatcher;

    try
    {
        MessageBox.Show("File changed.");

        watcher.EnableRaisingEvents = false; // Error: The name 'watcher' does not exist in the current context
    }
    finally
    {
        watcher.EnableRaisingEvents = true; //Error: The name 'watcher' does not exist in the current context
    }
}
nvoigt
  • 75,013
  • 26
  • 93
  • 142