Перехватывать вызовы меню "SendTo" MS Windows?

СЦЕНАРИЙ

Я управляю и упорядочиваю много файлов в течение дня, SendTo - самая используемая функция, которую я использую в Windows.

ПРОБЛЕМА

По умолчанию, когда пользователь нажимает элемент/ссылку контекстного меню для отправки файлов, ОС не показывает какой-либо совет/уведомитель, указывающий, что файлы копируются в выбранный пункт назначения.

Я считаю, что это очень неправильная проблема дизайна, потому что для больших файлов это ОК... будет отображаться индикатор прогресса, но если файлы будут небольшими, он не будет показывать индикатор прогресса/визуальный индикатор, поэтому невозможно гарантировать, что файлы скопированы (без ручного усилия), потому что я человек, и я мог щелкнуть вне контекстного меню SendTo по ошибке.

Итак, я хотел бы разработать персональный мини-инструмент, который поможет мне оптимизировать свое время, показывая мне окно уведомлений, где бы вы ни находились на экране, когда я отправляю/копирую файлы с помощью функции SendTo из контекстное меню и только SendTo.

Вопрос

В простых словах я хочу обнаружить операцию копирования/отправки из меню SendTo, чтобы убедиться, что щелчок был сделан правильно в пункте меню (а не вне меню), также предоставляя дополнительную базовую информацию, такую ​​как исходная папка, папка назначения и количество файлов или пути к файлам.

Любые идеи начать разработку этого инструмента в правильном направлении?

Я буду благодарен за пример кода в С# или еще VB.Net, желательно это последнее.

ПОДХОД

Поскольку я не знаю, как начать делать это, я имею в виду, какой может быть самый простой или эффективный способ перехвата этих вызовов SendTo, во-первых, я думал, что подключил CopyFile или CopyFileEx API, но они не предоставляют необходимую мне информацию, потому что эта функция будет вызываться в любой операции копирования, а не только при использовании функции SendTo, поэтому я теряюсь.

Я не уверен, что я должен больше исследовать внутренние вызовы или, возможно, больше узнать о самом контекстном меню windows, вместо того, чтобы возиться с перехватами функций и уродливыми вещами, которых я мог избежать.

Моя основная идея заключается в разработке скрытых WinForms (или службы Windows), которые остаются в фоновом режиме, ожидая, когда я использую функцию SendTo (когда я нажимаю на элемент SendTo), а затем отобразите на экране любой вид визуального индикатора, чтобы убедиться, что я правильно нажал этот пункт меню и, возможно, проинформирую о количестве файлов, которые я перемещаю и где я их перемещаю.

RESEARCH

Вот пример кода, который, по моему мнению, демонстрирует, как создать экземпляр объекта SendTo com, чтобы создать свой собственный?, но написанный на С++, и я не уверен, что этот пример полезен, мое намерение не заменять меню SendTo, но я сохраню эту полезную информацию здесь, она служит для чего-то еще:

Как добавить (включить) стандарт "Отправить в" контекстного меню в расширении пространства имен

KNOWNFOLDERID константы docs дает полезную информацию о папке SendTo снова я не уверен, что это может помочь, возможно, для подхода к мониторингу чтения/доступа?, я просто сохраняю информацию здесь:

GUID: {8983036C-27C0-404B-8F08-102D10DCFD74}

Путь по умолчанию:% APPDATA%\Microsoft\Windows\SendTo

Устаревший путь по умолчанию:% USERPROFILE%\SendTo

В Обработчики расширения оболочки docs есть Обработчик обработчика копирования, который я не знаю, имеет ли он связь с компонентом SendTo COM, и если что могло бы помочь мне каким-то образом, такое же незнание для ссылки IContextMenu:: InvokeCommand, которая, возможно, я могу перехватить ее, чтобы идентифицировать SendTo:

К моменту, когда я чувствую, что летаю слепой.

Недавно я нашел этот управляемый класс "Отправить в" , но снова его пример написан на C/С++ (я думаю, это тот же самый источник раньше), который я вообще не понимаю, и снова я не уверен, что это может мне помочь, потому что я повторяю, что замена SendTo - это не то, что у меня есть (просто потому, что я не знаю, как правильно это сделать, избегая всех возможных рисков, я предпочитаю, чтобы все еще позволял логике Windows копировать/отправлять файлы, я просто хочу обнаружить операцию копирования для получения информации)

Ожидаемые результаты и использование

Шаг 1:

Выберите случайный файл и используйте меню SendTo (на моем языке, на испанском языке, имя команды: Enviar a)

enter image description here

Шаг 2:

Пусть логика приложения .net(работающая в фоновом режиме) перехватит операцию SendTo для получения информации.

(Мне нужна помощь только с этим шагом)

Шаг 3:

Отобразите информацию где-нибудь на экране, чтобы убедиться, что была выполнена операция SendTo, чтобы я правильно нажал элемент SendTo ( My Link strong > ).

enter image description here

(Это всплывающее окно - просто симуляция, я не знаю, как получить всю эту информацию)

Ответ 1

Это очень просто сделать, как только вы поймете, что действительно делает SendTo, и вообще не включает COM или расширения оболочки. В основном, для отправки в меню заполняется содержимое папки SendTo профиля пользователя (C:\Users\\AppData\Roaming\Microsoft\Windows\SendTo по умолчанию в Windows 6.x).

Если щелкнуть, если этот параметр является ярлыком для папки, он скопирует туда файлы, но если есть ярлык для программы (или сам исполняемый файл программы), он запустит эту программу, пройдя пути выбранной файлы в качестве аргументов командной строки.

Оттуда очень сложно сделать некоторую программу, которая просто принимает пути как аргументы, представляет какое-то уведомление, а затем копирует файлы или делает с ними что угодно.

Быстрый и грязный пример может быть следующим (на С#, но может быть сделано с чем-либо еще на самом деле):

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));
}

Это просто попросит подтверждение для копирования нескольких файлов. Обратите внимание, что это действительно не "перехватывает" отправку в меню, а обрабатывает его полностью, поэтому он отвечает за выполнение каких-либо значимых действий. Более серьезная реализация может использовать встроенное диалоговое окно копирования Windows и отображать некоторые экраны с прогрессом или что-то еще, что соответствует вашим потребностям.

В командной строке может также потребоваться несколько параметров. Когда вы поместите ярлык в папку SendTo, пункт назначения может добавить еще несколько параметров, которые будут переданы в качестве первых (перед именами файлов). Например, назначение ярлыка может читать c:\program files\copyfiles.exe c:\temp для передачи целевой папки вместо жесткого кодирования. Затем вызываемая программа должна интерпретировать первый параметр как путь назначения и последующие в качестве исходных файлов.

Ответ 2

Я должен был сделать что-то подобное раньше. Вам даже не нужно перехватывать функцию SendTo(), вам нужно только убедиться, что файл появился. Как насчет FileSystemWatcher, если он находится на том же компьютере?

Вы можете использовать наблюдателя для просмотра, прежде чем отправлять его, а затем, если файл успешно достигнет цели, вы можете отобразить успешное сообщение и затем убить наблюдателя.

Пример кода

// 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 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();
}

Вы можете получить доступ к необходимой информации о свойствах (например, в вашем popup gif) следующим образом:

  • Имя папки: Path.GetDirectory(e.FullPath); (например, "C:\yo \" )
  • Полное имя файла: e.FullPath (например, "C:\yo\hey.exe" )
  • Имя файла: e.Name (например, "hey.exe" )

Процесс выполнения без кода:

  • Перед началом SendTo() создайте экземпляр свойства FileSystemWatcher и попросите его посмотреть конкретную комбинацию имен папок/файлов, которая должна отображаться в наблюдаемой папке: WatchFilesBeforeTransfer(FileName, DestinationFolder).
  • Инициировать SendTo().
  • Получен файл? DisplaySuccessfulSendToMessage(), KillFileWatcher();
  • ???
  • Profit.

UPDATE

Я просто понял, что только для одного файла. Если вы хотите проверить несколько файлов, вы можете либо создать несколько экземпляров FileWatcher (не рекомендуется), либо использовать объект List<string>, например:

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.
        }
    }
}

Надеюсь, это поможет!

Ответ 3

Боюсь, это не так просто. Я играл с FileSystemWatcher на этом, но с частичным успехом.

Что-то, что должно определенно работать, Драйверы файловой системы, но это тоже похоже, ну, посмотрите...

В конце концов, это может быть самый простой способ написать собственное расширение оболочки для доступа к папке SendTo и использовать это вместо команды SentTo, которая даст вам полный контроль.

Это могут быть некоторые запуски:

Расширения оболочки Windows

Контекстные меню оболочки