I need to monitor a file for changes and see exactly where it has been modified.
It seems like I can't use FileSystemWatcher as I only get notified that a file has been modified but I can't know exactly what changed, and storing copies of the file to do a diff after the event is raised is not feasible since the file is really big.
I would like to implement something like what SysInternals have on their Process Monitor software, that tells us, for a WriteFile event, the modified part of the file given an offset and length.
I read that there is a Windows API that does this, but I couldn't find anything on how or where to start implementing it on a .net 3.5 application.
From what I have investigated, the .NET platform provides this event for handling file change events. However, this alone will not let you know what part of the file has changed.
You will need to store somewhere a copy of the file that is compared to the file whenever it changes, and then update that copy when the comparison is done. This is a very basic solution and can get really inefficient if the file is too large.
Using the FileSystemWatcher you can subscribe to the changed event ChangedEvent
FileSystemEventArgs contains a property FullPath which can be passed in to FileInfo. This will give you some basic file information, which can be stored to a database for example. You can keep a history of the file changes this way.
If you need to compare the content of the files it is more challenging and the approach will be different depending on file type.
Related
I would like to either host a virtual drive and intercept the I/O, or intercept I/O calls to certain folders on a hard drive, and do arbitrary things to that call like write the file to a 2nd location. For example, if Notepad.exe writes a file to C:\Data\test.txt - I would like to have access to that file name, and the data of the file. Likewise, I would like to run arbitrary code when any user attempts to read C:\Data\test.txt or attempts to get a directory listing for C:\Data.
Ideally I want to have a handler for when a file is: created, updated, deleted, or opened - and when someone does a directory listing (from command-line or from the Shell).
I can do the write part with FileSystemWatcher - but I can't intercept disk "reads". So, I next looked into MS Detours and EasyHook. That won't really work because I'd need to monitor every single process on the computer and hook to OpenFile on ALL of them. I don't want to use a Shell Extension because this behavior needs to exist from the command-line too. So, that leaves either writing a File System MiniFilter driver - or writing my own installable file system in C++.
I can have some portion of this in C++ - although the driver stuff is a bit over my head, but ultimately most of the rest of code should be in C#, ideally.
Is there some straightforward way to intercept I/O to a specific folder or virtual drive? If the answer is with EasyHook or a MiniFilter, does anyone have any samples? EasyHook in particular only has samples from the late-2000s and the API has changed since then. Thanks!
Looks like an XY problem. What you seem to want are reparse point handlers.
Your example of "writing a file to another location" is just a link, and those already exist. Implemented by a standard reparse point handler.
You don't specify exactly what else you want to do, but similar things can be done by custom reparse point handlers. In short, a reparse point is a small bit of data in place of a file, which (1) specifies which handler should be called, and (2) provides custom data to that handler. For instance, the actual location of the file. Since it's custom data, you can use any format you like.
How would you go about detecting, blocking, or just in general referring to the Send File operation you can do to any file/folder on Windows. What exactly is happening when a send file happens and is there any kind of built in programmability in .NET or is it something similar to how doing a move works(It gets deleted first and then created in the new location.)
I just want to know if there is any way to detect when a Send File happens or what windows does with the file/folder when a send file is executed.
If you are speaking of the "Send To" context menu when you right-click on a file/folder, that is the result of a shell extension handler. Pretty sure there's now way to intercept those:
Is there a Click Handler for Shell Extension
MS documentation on registering/creating your own handers is below:
http://msdn.microsoft.com/en-us/library/windows/desktop/cc144067%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/cc144110%28v=vs.85%29.aspx
I presume that if you select "Send To" and pick a folder/drive, then it would do a standard move or copy (depending on if it is the same drive or not). As mentioned by Alan, you can use a FileSystemWatcher to try and monitor specific files/directories, but be careful being over broad with what you are watching, because there are limitations on how fast FSW can receive events, meaning if you watch to much you will miss events. Another option if you absolutely must see the file move would be to hook into the Change Journal, but that gets really ugly.
If you want to stop someone from moving or copying a file, you would have to alter its permissions for read and/or modify to exclude the user.
There is a FileSystemWatcher class that may help you detect changes to the file system. Also, the File Class has a static method for Move and other file operations. You may look into the System.IO namespace
When you move a file, it doesn't usually get recreated and deleted (if they are on the same device). Usually its location is just modified. (hence it happens almost instantly even on large files)
I am working on an application that keeps track and uses files stored on the file system. Users are allowed to open, create, delete and move files in the file system. Meanwhile my application is not constantly running so I can't keep track of all changes real-time. Afterwards my application has to find out what file is whom (i.c. as identified in my application).
The most preferred solution for the users is that the application solves every change itself. Each user-interaction is less preferred.
One of my ideas was to use an attribute of a file and assign a key-value to it so when it has been identified once, it can always been recognized afterwards. But I don't know if there is such an attribute. This article didn't give much hope: There is in Windows file systems a pre computed hash for each file?.
Does somebody know if there is such an attribute I can use? And how can I used it in C#?
Is there anyone who is running up against this problem? And how did you solve it?
I'd like to hear good suggestions.
regards, Jaap
If your files don't leave NTFS, this is easily achievable by alternative data streams, where you can store your data along with files. This is more-or-less good article about ADS: http://www.flexhex.com/docs/articles/alternate-streams.phtml
There is another suitable method - it's very efficient, but also very complicated to use, it requires quite good knowledge about NTFS internals - USN Change Journal; see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363798.aspx. With USN Change Journal, you can "get" very efficiently all files that were changed (even all change events) within specified time period.
Nevertheless, if your files leave NTFS realm, e.g. if it's copied to FAT32, contents of ADS is lost.
Relying on a File attribute is "dangerous" in that some user could alter the attribute while your program isn't running. This could lead you to believe that a certain file is (or isn't) tracked by the program while it really isn't.
I would suggest to keep track of the files in a database, XML, or some other file. When your application starts you read the file/db and check for new/deleted/editted files.
You could store a Hash of the files to find out if a file has been moved/editted. Keeping track of files that are moved AND editted is going to be pretty difficult. (I have no clue how you could achieve it)
PS: Have you considered making your application a Windows service? Having the file-management running in the background no matter if the GUI part of your application is running or not?
I have come across several "solutions" here and across the web but none seem to fit the bill.
What I am looking to do is have an app monitor a folder for new files (either by creation, a move, or a copy) and perform actions on those objects. That being the scenario, I turned to the FileSystemWatcher class to perform this action.
The problem is that the file FileSystemWatcher.Created event is fired before the entire file is created (most noticeably seen through a copy of a large file).
Is there any way to have this event fire at the conclusion of the file creation as opposed to the beginning? I have tried various combination's of the FileSystemWatcher.NofityFilter property with no success.
Thanks in advance! :)
I have used a couple of solutions for this situation.
If you can work with the creator of the file and use a renaming scheme for the file. EG. Create the File as __Name_ while being created and at the end of the process rename it to Name and the event will fire and you have a complete file.
When your trigger fires check if you can get an exclusive readonly lock on the file. If you can then the write operation has been completed to the file. (I wrote something about this in another question Keep settings in sync between forms application and windows service (or any n-tier, really))
You could possibly integrate something like #2 into your Changed Event and then you'll get the result.
Hmm interesting problem. I never used the object while watching for big files. Did a little searching and seems one solution is to monitor the Changed event as well. Because once the file is done copying (after created is fired) a changed event is thrown as well (cause the file increased in size)
More details from what I read here: http://social.msdn.microsoft.com/forums/en-US/vblanguage/thread/f84bb7c8-b7d5-44da-b0f3-6d1a70415d11/
I know, that what I am going to tell you does not look elegant. I had also to monitor files that arrive from different places, some of them were large and some small. We found out, that FileSystemWatcher is not reliable for this purpose. If you want to be 100% sure, you can check once in a while, using Timer class and its Elapsed event.
You would need to track closing of the file after it's creation and I doubt it's possible with FileSystemWatcher.
If you don't find a solution with FileSystemWatcher, take a look at our CallbackFilter product, which lets you track all operations in real-time.
I'm looking for a way to determine if a file has been executed or not. I've looked a bit into FileInfo's LastAccessTime but this doesn't seem to change when a file is executed. I've also looked into FileSystemWatcher but this also doesn't seem to offer a solution. Is there such a thing as a file execution listener or is there another way? If it helps, i'm looking to write a folder listener that renames an .avi file within it after it has been watched/executed.
There is a distinction between file being "executed" (e.g. a portable executable file, like an "exe") and a file being "accessed" (e.g. an AVI file that is "played" by another exe).
It sounds like you are looking in the right place and you will want the "LastAccessTime" but, be aware that resolution of the Access time is dependent on the file system... On NTFS it's a full date/time, on FAT it's just the date (hence it won't change if it's already been accessed that day.)
Actually, LastAccessTime might be what you want, since AVI files aren't "executed", only opened. I have, in the past, used it for exactly the purpose you describe, but not programmatically.
Just for the sake of completeness: Windows does not keep execution history, at least not publicly.
Edited to add:
According to MSDN, LastAccessTime is your best shot, however:
Note This method may return an inaccurate value, because it uses native functions whose values may not be continuously updated by the operating system.
But this is followed a few lines later by:
To get the latest value, call the Refresh method.
(This refers to FileSystemInfo.Refresh.)
It's all a little obtuse, if it doesn't work exactly as documented I wouldn't be surprised.
Hmmm, I'm not too sure about finding out if a file has be run, but what might be a better approach would be to monitor the media player to determine when a video has finished playing.