Hooking my program with windows explorer's rename event - c#

Is there any way, in any language, to hook my program when a user renames a file?
For example:
A user renames a file and presses enter (or clicks away) to confirm the rename action. BEFORE the file is actually renamed, my program "listens" to this event and pops up a message saying "Are you sure you want to rename C:\test\file.txt to C:\test\test.txt?".
I'm thinking/hoping this is possible with C++, C# or .NET.. But I don't have any clue where to look for.

You can probably solve this by using the FileSystemWatcher class in .NET framework.
From the class remarks:
You can watch for renaming, deletion,
or creation of files or directories.
For example, to watch for renaming of
text files, set the Filter property to
"*.txt" and call the WaitForChanged
method with a Renamed specified for
its parameter.

My guess is that this is not possible, I did find this which is for monitoring operations (including rename) on a folder, but there does not appear to be a similar method for files.
#Richard, FileSystemWatcher is good if you only need to monitor changes, but he needs to interrupt them which it cannot do.

IFileOperationProgressSink.PreRenameItem is the closest supported thing I know of. Unfortunately, it's not a hook into Explorer - so you can only use it for your own IFileOperation actions. Depending on your needs, you can write a shell extension to do your own ConfirmRename (or something), and branch from there.
Otherwise, you're looking at hooking SHFileOperation, I think. This would have to be done in unmanaged code, as you'll be loaded into Explorer.exe. For Vista, this has been changed to IFileOperation - which probably means you'll have to hook the creation of it and pass out your mock.
Personally, I think since you're talking a rename, wilhelmtell's idea of confirming after the change, and undoing it if necessary is the best idea.

Related

How to intercept Win32 API calls with C#?

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.

Send File Programmability in C#

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)

Allow User to Delete File In Use By My Application?

Can I allow a user to delete a file, under Windows, that is in use by my application?
In my scenario I have a "quick add" directory that is monitored by my application. When it sees a new image show up it creates a new slide to display in an automated slide show. I would also like to allow my users to delete (and/or rename) a file from my "quick add" directory, and remove it from the slide show.
Is there a way I can flag the file that notifies Windows that I'm okay for it to remove the file while my application is using it?
Is there a way I can flag the file that notifies Windows that I'm okay for it to remove the file while my application is using it?
Yes. In Win32 this is dwShareMode passed to CreateFile(). This is a bitfield of what you would like to permit another process to do. The bit you are looking for is FILE_SHARE_DELETE which allows a delete or a rename while open. However, for the most polite behavior I would recommend including all 3, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE.[1]
Since you're asking about C# and not Win32, in the .NET world these are included in the FileShare enumeration which you can pass when opening a file, eg. in File.Open.
Note that these flags don't let you allow a rename of a file's parent directory while it is opened by name. That will fail regardless of sharing due to limitations in the kernel (technically in ntfs.sys IIRC).
Footnote
1: Editorial comment: It is a shame that passing 0 (which many people do without thinking) happens to be the least permissive option, or that more people writing code on Windows don't realize what this parameter does and pass these three flags.
If you call a Delete() or Rename() method onto the Control that is using the file, you can remove it from the PictureBox before it deletes or renames the file.
There shouldn't be much of an issue with doing multiples. With a Checkbox on the Control, you just check each Control to see if that property is true, then call the appropriate method.

How to track directory opening

I'm not sure if the question's title makes sense, and I'm sorry if it doesn't; I didn't really know what to title it.. Anyway, is there a way to make your program track the viewing of a folder?
What I'm trying to achieve: Windows 7 Home Premium doesn't allow encryption. So, I made a folder inside my user directory, and set it to hidden. Although, you can easily find it by changing windows settings.. So, is there a way to make a program pull up a window if the user tries to access that certain folder?
I don't think you can detect the "opening" of a folder.
Instead, you may want to set a FileSystemWatcher to detect any file access to the files in that particular folder.
Hope this helps.
First of all, I have to wonder why you're not just setting an ACL on the directory to prevent access.
However, it sounds like you want to find when somebody is accessing a particular directory. To do this, you enable filesystem auditing, then set the audit ACL to generate audit entries for "List folder". This will cause entries to be generated in the Security Event Log whenever the directory is viewed.
Now you just have to write a program that watches the Security event log looking for entries indicating that somebody has listed the directory in question and take action as necessary.
Well, there is an article on code project describing how you can hook into windows system calls: http://www.codeproject.com/KB/system/hooksys.aspx - it's not simple though (and also not C#) and has the potential to screw with your system but if it might be a fun project to work on.
A simpler option would be: Use a 3rd party desktop encryption tool - not much programming involved here but it might do the job better than anything else.

Is there way to determine if a file has been executed or not in C#?

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.

Categories