Gabriel Solitario
Gabriel Solitario

Reputation: 123

Handle system folders event in windows

I am writing some C# code and I need to detect if a specific folder on my windows file system has been opened while the application is running. Is there any way to do it? WinAPI maybe?

Upvotes: 8

Views: 2744

Answers (6)

Brad
Brad

Reputation: 1529

You could use the FileSystemInfo's LastAccessProperty. The problem though is that it can be cached.

FileSystemInfo: http://msdn.microsoft.com/en-us/library/975xhcs9.aspx

LastAccessTime Property: http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.lastaccesstimeutc.aspx

As noted that this can be pre-cached.

"The value of the LastAccessTimeUtc property is pre-cached if the current instance of the FileSystemInfo object was returned from any of the following DirectoryInfo methods:

GetDirectories

GetFiles

GetFileSystemInfos

EnumerateDirectories

EnumerateFiles

EnumerateFileSystemInfos

To get the latest value, call the Refresh method."

Therefore call the Refresh method but it still might not be up to date due to Windows caching the value. (This is according to msdn doc "FileSystemInfo.Refresh takes a snapshot of the file from the current file system. Refresh cannot correct the underlying file system even if the file system returns incorrect or outdated information. This can happen on platforms such as Windows 98." - link: http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.refresh.aspx

Upvotes: 0

bigtlb
bigtlb

Reputation: 1572

Go with the Windows Shell Extensions. You can use Shell Namespace Extensions to make a "virtual" folder that isn't there (or hides a real one), like the GAC (C:\Windows\assembly)

Here are several examples of Shell Extension coding in .Net 4.0.

A Column Handler would let you know when a folder is "Opened", and even let you provide extra data for each of the files (new details columns).

Upvotes: 1

Alex
Alex

Reputation: 23300

I think the only way you can reliably achieve this is by monitoring the currently running processes and watch closely for new Explorer.exe instances and/or new Explorer.exe spawned threads (the "Run every window on a separate process" setting gets in the way here).

I admit I don't have a clue about how to code this, but that's what I would look for.

Upvotes: -2

sqykly
sqykly

Reputation: 1586

There are three API things I think you should check out:

FindFirstChangeNotification() http://msdn.microsoft.com/en-us/library/aa364417%28VS.85%29.aspx That gives you a handle you can wait on and use to find changes to a file in a particular file, directory, or tree of directories. It won't tell you when a directory is browsed, but it will tell you when a file is saved, renamed, and so on and so forth.

SetWindowsHookEx() http://msdn.microsoft.com/en-us/library/ms644990%28v=VS.85%29.aspx You can set that up to give you a callback when any number of events occur - in fact I'm pretty positive that you CAN get this callback when a directory is opened, but it will probably be inordinately difficult because you'll be intercepting messages to explorer's window. So you'll be rebooting during debugging.

Windows Shells http://msdn.microsoft.com/en-us/library/bb776778%28v=VS.85%29.aspx If that wasn't painful enough, you can try writing a shell program.

If you're trying to write a rootkit, I suppose you don't want me to spoil the details for you. If you're NOT trying to write a rootkit, I suggest you look it up - carefully. There are open source rootkits, and they all basically have to monitor file access this way to hide from the user / OS.

Upvotes: 2

Dubs
Dubs

Reputation: 124

The closest thing that I can think of, that may be useful to you, is using the static Directory class. It provides methods to determine the last time a file or directory was accessed. You could setup a BackgroundWorker to monitor if the directory was accessed during a specified interval. Keep track of the start and end of the interval by using DateTime, and if the last access time falls between those, then you can use the BackgroundWorker's ProgressChanged event to notify the application.

 BackgroundWorker folderWorker = new BackgroundWorker();
 folderWorker.WorkerReportsProgress = true;
 folderWorker.WorkerSupportsCancellation = true;
 folderWorker.DoWork += FolderWorker_DoWork;
 folderWorker.ProgressChanged += FolderWorker_ProgressChanged;

 folderWorker.RunWorkerAsync();

 void FolderWorker_DoWork(object sender, DoWorkEventArgs e)
 {
      BackgroundWorker worker = (BackgroundWorker)sender;

      while(!worker.CancellationPending)
      {
           DateTime lastAccess = Directory.GetLastAccessTime(DIRECTORY_PATH);

           //Check to see if lastAccess falls between the last time the loop started
           //and came to end.
           if(/*your check*/)
           {
                object state;  //Modify this if you need to send back data.
                worker.ReportProgress(0, state);
           }
      }
 }

 void FolderWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
 {
      //Take action here from the worker.ReportProgress being invoked.
 }

Upvotes: 0

Chuck Savage
Chuck Savage

Reputation: 11955

Check out the FileSystemWatcher class.

Upvotes: 0

Related Questions