Intercept MS Windows 'SendTo' menu calls? Intercept MS Windows 'SendTo' menu calls? windows windows

Intercept MS Windows 'SendTo' menu calls?


It's really simple to do once you understand what SendTo really does, and it doesn't involves COM or shell extensions at all. Basically, the send to menu is populated with the content of the SendTo folder of the user profile (C:\Users\\AppData\Roaming\Microsoft\Windows\SendTo by default in Windows 6.x).

When clicked, if the option is a shortcut to a folder it will copy the files there, but if there is a shortcut to a program (or a program executable itself) it will run that program, passing the paths of the selected files as command-line arguments.

From there, it's really trivial to make some program that simply takes paths as arguments, present some kind of notification and then copies the files or do whatever you want with them.

A quick and dirty example could be as follow (in C#, but could be done with anything else really):

private static void Main(string[] args){    if(MessageBox.Show("Are you sure you want to copy files?", "Copy files", MessageBoxButtons.YesNo) == DialogResult.No) return;    foreach (string file in args)        File.Copy(file, Path.Combine("c:\\temp", Path.GetFileName(file));}

This just ask for confirmation for copying a bunch of files. Note that this really doesn't "intercepts" the send to menu, but rather handles it completely, so it's the program responsability to do any meaningful action. A more serious implementation could use the built-in Windows copy dialog and display some screen with progress or anything else, that's up to your needs.

It could also take some more parameters on the command line. When you place a shortcut in the SendTo folder, the destination could add some more parameters that will be passed as the first ones (before the file names). For example the destination of the shortcut can read c:\program files\copyfiles.exe c:\temp to pass the destination folder instead of hardcoding. The called program must then interpret the first parameter as the destination path and subsequent ones as the source files.


I've had to do something like this before. You don't even have to intercept the SendTo() function, you only need to make sure the the file has arrived. How about FileSystemWatcher if it's on the same computer?

You could use a watcher to watch before you send it, then, if the file successfully arrives at it's destination, you can display a successful message, and then kill the watcher.

Code Example

// Create a FileSystemWatcher property.FileSystemWatcher fsw { get; set; }// So we can set the FileToWatch within WatchFilesBeforeTransfer().private string FileToWatch { get; set; }private void WatchFilesBeforeTransfer(string FileName, string DestinationFolder){    fsw = new FileSystemWatcher();    fsw.Path = DestinationFolder;    FileToWatch = FileName;    // Only if you need support for multiple directories. Code example note included.    fsw.InclueSubdirectories = true;     // We'll be searching for the file name and directory.    fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName     // If it's simply moving the file to another location on the computer.    fsw.Renamed += new RenamedEventHandler(FileRenamed);     // If it was copied, not moved or renamed.     fsw.Created += new FileSystemEventHandler(FileCreated);    fsw.EnableRaisingEvents = true;}// If the file is just renamed. (Move/Rename)private void FileRenamed(Object source, RenamedEventArgs e){    // Do something.    // Note that the full filename is accessed by e.FullPath.    if (e.Name == FileToWatch)     {         DisplaySuccessfulMessage(e.Name);         KillFileWatcher();    }}// If creating a new file. (Copied)private void FileCreated(Object source, FileSystemEventArgs e){    // Do something.    // Note that the full filename is accessed by e.FullPath.    if (e.Name == FileToWatch)     {         DisplaySuccessfulMessage(e.Name);         KillFileWatcher();    }}private void KillFileWatcher(){   fsw.Dispose();}

You can access the desired property information (like in your popup gif) in this way:

  • Folder name: Path.GetDirectory(e.FullPath); (like "C:\yo\")
  • Full file name: e.FullPath (like "C:\yo\hey.exe")
  • File name: e.Name (like "hey.exe")

Non-code execution process:

  1. Before you initiate SendTo(), create an instance of the FileSystemWatcher property, and have it watch for a specific Folder/File name combination, which should show up in the watched folder: WatchFilesBeforeTransfer(FileName, DestinationFolder).
  2. Initiate SendTo().
  3. File received? DisplaySuccessfulSendToMessage(), KillFileWatcher();
  4. ???
  5. Profit.

UPDATE:

I just realized that's just for one file. If you want to check for multiple files, you could either create multiple FileWatcher instances (not recommended), or use a List<string> object, like this:

private void SendTo(List<string> FileCollection){    // Clear your previous FileList.    FileList.Clear();    foreach (string file in FileCollection)    {        FileList.Add(file);     }    // Rest of the code. }List<string> FileList { get; set; }private void WatchFilesBeforeTransfer(string DestinationFolder){    // Same code as before, but delete FileToWatch.}private void FileRenamed(Object source, RenamedEventArgs e){    foreach (string file in FileList)    {        if (e.Name == file)        {            // Do stuff.        }    }}private void FileCreated(Object source, FileSystemEventArgs e){    foreach (string file in FileList)    {        if (e.Name == file)        {            // Do stuff.        }    }}

Hope this helps!


I'm afraid this ain't that easy.I was playing around with the FileSystemWatcher on this, but with only partly success.

Something that should definitely work are File system drivers but this looks like just too, well, look at it...

In the end it might be the easiest way to write your own shell extension to access the SendTo folder, and use this instead of the SentTo command which would give you full control.

These might be some starters:

Windows shell extensions

Shell Context Menus