This question already has answers here:
C# : file copy notifying [closed]
(2 answers)
Closed 9 years ago.
I am trying to keep track of files that are copied by users and other applications.
The FileSystemWatch only has events for Changed, Created, Deleted, Disposed, Error, and Renamed.
It doesn't fire an event when a file is accessed by the copy function or where the new file is being copied to.
Is there a method for monitoring the copy event/function of windows?
I don't know of any way using C#.
You can do this if you are willing to write a File System Filter Driver. [Definitely expert territory, as there is scope for corrupting files and/or bringing down your system]
A file system filter driver intercepts requests targeted at a file
system or another file system filter driver. By intercepting the
request before it reaches its intended target, the filter driver can
extend or replace functionality provided by the original target of the
request. Examples of file system filter drivers include anti-virus
filters, backup agents, and encryption products. To develop file
systems and file system filter drivers, use the IFS (Installable File
System) Kit, which is provided with the Windows Driver Kit (WDK).
You are doing the right thing with FileSystemWatcher. Windows does not have any built-in mechanism for reporting copies reliably.
You could hook the OS copy routine, but this won't guarantee you good results: applications are free to implement their own copy by just opening the source and destination files and copying the bytes over.
Renaming is different because a rename done by the OS cannot be easily mimicked through other means, so you will catch all renames with the FileSystemWatcher. Note that moving between drives is more like copy: you won't get a Renamed notification, but a Created and a Deleted instead.
So if you really really need to notice a file getting copied, my suggested approach is this:
Hook the CloseFile calls, in addition to the FileSystemWatcher.
Whenever a file gets closed, it could be because it's the source or target of a copy / cross-drive move. Check its size.
If you find two closed files with the same size within a reasonably short period of time, compare the content. Pretty resource-intensive, but the only reliable way to do this.
You can use Auditing file and folder access feature of Windows which writes an event log entry and you can setup programs to start when such an event occurs
I can't think of any good way.
For each newly created file, you need to check if there is an exact duplicate (perhaps with a different name) anywhere on the filesystem. You could obviously do this brute-force, but the solution would be very inelegant, slow and brittle!
Related
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?
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can one add custom properties to NTFS folders?
I am trying to write a standalone executable in C# that attaches a value to a text file (without changing the content of the file) which can be read later.
I have looked into the following solutions but none of them quite work:
Shell32.dll: Only appears to allow reading the properties. I could not find any information on how to use Shell32 to write properties.
DSOFile: App needs to be standalone and I am also concerned about future OS compatibility.
NTFS Alternate Data Streams (ADS): Many tools will not copy this information if the file is moved or copied and I am concerned about future compatibility.
Is there another way (COM, Etc..) to attach a custom property to a text file in .NET?
The only three ways I can think of:
ADS - however you've already dismissed this.
Add it to the file name.
Add it to the beginning or end of the file.
If it's an application controlled file that may be moved around then your best bet is number two. Of course, this means that the file may "lose" that info in a renaming operation.
The third option is a bit iffy. If you can control how the file is viewed, then you can simply give it a different extension and write your data to the top of it. When it needs to be opened you can "extract" the real file and open accordingly. I think this is WAY more complicated... but it will contain your data and be less likely to be jacked with.
I am by no means a programmer but currently am wondering if an application creates a temp file that windows names. For example the file it creates is tmp001, is there a way i can take that name tmp001 and ask windows to give me the next temp file it would create before it creates it.
Thanks,
Mike
There is no direct means to get to know the next temporary filename to be created.
For example, programmers use the System.IO.Path.GetTempFileName method, but one can add application-specific prefixes or suffixes in order to make it easier for the application to find its newly created files.
One can even choose to save this temporary file elsewhere than the system Temp folder.
You would need to define a "temp file" much more explicitly in order to answer this question with a "Yes". The problem is that a "temp file" is just something not meant to be kept. It could exist anywhere on the system and be created by a user, application, or service. This would make it nearly (or actually) impossible to answer your question with a "Yes".
If you constrain the definition of a temp file to just the files in the official temp folder (or a subfolder), you still have a problem if you're trying to catch names not generated by windows. Any app could produce a particularly named temp file in that folder, without Windows caring.
If you further constrain the definition to be only those files named by Windows, you might be able to get somewhere. But, does that really meet your needs?
After all of that, maybe it would be better to describe the problem you're trying to solve. There may be a much better (workable) solution that would address the issue.
Typically applications use the Win32 API GetTempFileName to get the temporary directory.
The process of how the temp file is generated is described there.
I'm not sure why you want this info, but perhaps you could for example register for directory changes via a Win32 API like ReadDirectoryChangesW or by using a mini filter driver.
This kind of code just cannot work reliably on a multi-tasking operating system. Another thread in another process might pre-empt yours and claim the file name you are hoping to create.
This is otherwise easy enough to work around, just name your own files instead of relying on Windows doing it for you. Do so in the AppData folder so you'll minimize the risk of another process messing it up.
I want to write a program that will encrypt an entire folder and it's sub-folders, I have no problem doing this but I would like to make the entire encryption process rather transparent by letting a user double click it and have it open as if it weren't encrypted, say if it were a picture or a word document and it'd open in it's respective application.
How can a running program of mine become notified about the opening of a target file, stop the file from opening, do what it needs to do (decrypt), followed by running the resulting decrypted file.
How can I watch a file and do this in C#? Can I watch for other interactions like the user copying a watched file (since it won't be in a watched folder, it should be decrypted i.e. it's dragged to a USB device), or for deleting a watched file (say if I want to shred a file before deletion)?
P.S. The FileSystemWatcher doesn't quite meet my needs. EDIT: What I mean is that FileSystemWatcher will tell me when a file is being opened, deleted and all those events, but it won't let me step in real quick, decrypt the file, and hand it back to the process that normally opens that file.
You can rename files, add them your own extension, like thepicture.jpg.encrypted. Set your program as a default program for this extension and handle opening them
It's impossible in C#. the bare minimum would need you to use user-mode hooks on NtCreateFile, NtOpenFile, etc. You can't achieve that in C#. That wouldn't even work properly due to kernel-mode code which may try to access your files. The proper way of doing this would be to write a I/O minifilter (in C of course).
EDIT: If you're really desperate, try EasyHook - it allows you to hook functions from C#. I haven't tried it though, and it does seem risky hooking vital functions like NtCreateFile. Plus you need a fair bit of Native API knowledge.
Are you using Windows? If so, why not use the built-in BitLocker?
See this link:
BitLocker drive encryption
If you are thinking about a competitive application to BitLocker, add a comment, as I can point you in that direction as well.
Instead of trying to reinvent the wheel, use NTFS file encryption. You can encrypt single files or entire folders or drives. Plus it's completely transparent to the user and does exactly what you asks (e.g. automatically decrypt when copying to a UBS drive, etc). Just use System.IO.File.Encrypt(string) - there couldn't be anything easier.
You can't do this from usermode.
Unfortunately the only way to do this is to write a minifilter driver. Minifilter drivers allow you to intercept IO requests to files, you can then encrypt/decrypt the files you care about on the fly.
It sounds simple, but encryption minifilter drivers are very, very, difficult to get right. You will have to end up shadowing file objects which is a real challenge. Check with www.osr.com, they have a ton of information on doing exactly what you want to do.
If you choose to go this route I would recommend getting a copy of VMWare Workstation and download VirtualKD. It will let you debug at near fire-wire speeds into a VM. I would start with x64 Win7 and get remote shares working first.
Following up from this question: How can I unlock a file that is locked by a process in .NET, how do I programmatically get a list of files that are locked in a particular folder and its subfolders?
I'm using Windows 2003, .NET 3.5, C# 3.0.
Update: some background... basically we're archiving closed websites on a shared server. After deleting the site from IIS we move the folder structure for the site to an archive where it's held for 6 weeks. Even though the IIS site and FTP has been stopped and deleted we still encounter locked files during the move. So it'd be nice to know upfront what's still got a lock on it.
As answered in another question :How to check for file lock?
The only way would be trying them all and add them to the list if it throws an exception.
As mentioned in the above question, it would not be a reliable list to use, but only give you an overview of a specific point in time.
The only reliable way to detect locked files in real time would be to write a device driver (like filemon), but I don't think you can do that in C#.