Как создать контекстное меню для моего программного обеспечения?

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

Я хочу узнать, как сделать их для разных ОС, независимо от архитектуры:)

  • Что называются этими меню? Я имею в виду собственное имя, поэтому в следующий раз я смогу сослаться на них более четко.
  • Как это сделать?

Мое первоначальное понимание:

Я думаю, что это будет сделано: передайте файл как аргумент методу main(), а затем оставьте остальную часть обработки мне:)

1 ответ

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

К сожалению, самый простой способ создать контекстное меню с помощью Java - это редактирование реестра. Я попытаюсь обобщить основные этапы общих требований и шагов для достижения нашей цели.

< ОБНОВЛЕНИЕ> См. В конце сообщения для ссылок на образец кода и рабочую демонстрацию.

Что нужно сделать

  • Нам нужно изменить реестр, добавив дополнительную запись (для нашего java-приложения) в контекстные меню интересующих нас типов файлов (например, .txt, .doc, .docx).

    • Нам нужно определить, какие записи в реестре будут редактироваться, потому что наши целевые расширения файлов могут быть связаны с другим "классом" (я не смог проверить его на XP, но в Windows 7/8 это похоже на это так). Например. вместо редактирования ...\Classes\.txt нам может потребоваться отредактировать ...\Classes\txtfile, с которым связан класс .txt.

    • Нам нужно указать путь к установленному jre (если мы не можем быть уверены, что каталог, содержащий javaw.exe, находится в переменной PATH).

    • Нам нужно вставить правильные ключи, значения и данные в соответствующие узлы реестра.

  • Нам нужно java-приложение, упакованное как .JAR файл, с методом main, ожидающим массив String, содержащий одно значение, которое соответствует пути файла, который нам нужно обработать (ну, что просто часть - просто указывая очевидное).

Все это легче сказать, чем сделать (или наоборот)? Поэтому давайте посмотрим, что нужно сделать, чтобы сделать каждый.

Прежде всего, есть некоторые предположения, которые мы будем делать для остальной части этого поста (для простоты/ясности/краткости и т.п.).

Предположения

  • Мы предполагаем, что целевая файловая категория - это файлы .txt - те же самые шаги могут быть применены для каждой категории файлов.
  • Если мы хотим, чтобы изменения (например, контекстные меню) затрагивали всех пользователей, нам нужно изменить ключи реестра под HKCR\ (например, HKCR\txtfile), что требует административных привилегий. Для простоты мы предполагаем, что нужно изменить только текущие пользовательские настройки, поэтому нам нужно будет редактировать ключи под HKCU\Software\Classes (например, HKCU\Software\Classes\txtfile), что требует не административных привилегий. Если вы решите перейти на общесистемные изменения, необходимы следующие изменения:
    • Во всех командах REG ADD/DELETE замените HKCU\Software\Classes\... на HKCR\... (do not замените его в командах REG QUERY).
    • Попросите ваше приложение работать с административными привилегиями. Здесь есть два варианта (что я знаю):
      • Поднимите свои привилегии для запуска (может быть сложнее с последними версиями окон, из-за UAC). Есть много ресурсов онлайн и здесь, в SO; этот кажется многообещающим (но я сам его не тестировал).
      • Попросите пользователя явно запустить приложение "Как администратор" (используя правую кнопку мыши → "Запуск от имени администратора" и т.д.).
  • Мы предполагаем, что нужны только простые элементы контекстного меню (в отличие от контекстного подменю с большим количеством записей). После некоторых (довольно мелких) исследований я пришел к выводу, что для добавления подменю в более старых версиях Windows (XP, Vista) потребуется более сложный материал (ContextMenuHandlers и т.д.). Добавление подменю в Windows 7 или новее значительно проще. Я описал процесс в соответствующей части этого ответа (рабочая демонстрация предоставлена;)).

Тем не менее, переходим к...

Выполнение работ

  • Вы можете выполнить редактирование реестра, выпустив команды формы REG Operation [Parameter List], с операциями с участием ADD, DELETE, QUERY (подробнее об этом позже). Чтобы выполнить необходимые команды, мы можем использовать экземпляр ProcessBuilder. Например.

    String[] cmd = {"REG", "QUERY", "HKCR\\.txt", "/ve"}; new ProcessBuilder(cmd).start(); // Executes: REG QUERY HKCR\.txt /ve

    Конечно, мы, вероятно, захотим захватить и обработать возвращаемое значение команды, которое может быть выполнено через соответствующий процесс getInputStream(). Но это попадает в сферу "детали реализации"...

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

      // This checks the "Default" value of key 'HKCR\.txt' REG QUERY HKCR\.txt /ve

      // Possible output: (Default) REG_SZ txtfile

      Все, что нам нужно, проанализирует вышеприведенный вывод и узнает, если значение по умолчанию пустое или содержит имя класса. В этом примере мы видим, что связанный класс txtfile, поэтому нам нужно отредактировать node HKCU\Software\Classes\txtfile.

    • Задание пути jre (точнее путь к javaw.exe) выходит за рамки этого ответа, но должно быть много способов сделать это (я не знаю ни одного, я бы на 100% доверие, хотя). Я просто перечислил несколько из головы:

      • Ищем переменную окружения 'JAVA_HOME' (System.getenv("java.home");).
      • Глядя в реестр на значение типа HKLM\Software\JavaSoft\Java Runtime Environment\<currentversion>\JavaHome</currentversion>.
      • Поиск в заранее определенных местах (например, C:\Program Files[ (x86)]\Java\).
      • Запрос пользователю указать его в JFileChooser (не очень хорошо для неопытного пользователя).
      • Использование такой программы, как Launch4J, для переноса вашего .JAR в .EXE(что избавляет от необходимости определять путь к "javaw.exe" самостоятельно).

Последние версии Java (1.7+?) помещают копию javaw.exe (и других утилит) в путь, поэтому также стоит проверить это.3. Итак, после сбора всех необходимых данных, идет основная часть: Вставка необходимых значений в реестр. После выполнения этого шага наш HKCU\Software\Classes\txtfile - node должен выглядеть следующим образом:

HKCU
|_____Software
 |_____Classes
 |_____txtfile
 |_____Shell
 |_____MyCoolContextMenu: [Default] -> [Display name for my menu-entry]
 |_____Command: [Default] -> [<my_command>]*
*: in this context, a '%1' denotes the file that was right-clicked.
</my_command>

На основе того, как вы решили шаг (1.2), команда может выглядеть так: "C:\Path\To\javaw.exe" -jar "C:\Path\To\YourApp.jar" "%1" Заметьте, что javaw.exe обычно находится в ...\jre\bin\ (но не всегда только) - недавно я нашел его в C:\Windows\System32\).

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

REG ADD HKCU\Software\Classes\txtfile\Shell\MyCoolContextMenu /ve /t REG_SZ /d "Click for pure coolness" /f
REG ADD HKCU\Software\Classes\txtfile\Shell\MyCoolContextMenu\Command /ve /t REG_SZ /d "\"C:\Path\To\javaw.exe\" -jar \"C:\Path\To\Demo.jar\" \"%%1\" /f"
 // Short explanation:
 REG ADD <path\to\key> /ve /t REG_SZ /d "<my_command>" /f
 \_____/ \___________/ \_/ \_______/ \_______________/ \_/
 __________|_______ | | |___ | |
|Edit the Registry | | _______|________ | _______|_______ |
|adding a key/value| | |Create a no-name| | |Set the data | |
-------------------- | |(default) value | | |for this value.| |
 | ------------------ | |Here: a command| |
 _______________|______________ | |to be executed.| |
 |Edit this key | | ----------------- |
 |(creates the key plus | ____|_________ _________|_____
 | any missing parent key-nodes)| |of type REG_SZ| |No confirmation|
 -------------------------------- |(string) | -----------------
 ----------------
</my_command></path\to\key>

Рекомендации по внедрению:

  • Вероятно, неплохо проверить, имеет ли наш целевой класс (например, txtfile) элемент контекстного меню с именем "MyCoolContextMenu", иначе мы могли бы переопределить существующую запись (которая не сделает нашу пользователь очень счастлив).
  • Поскольку часть данных значения (часть, которая приходит после /d и до /f) должна быть заключена в "", имейте в виду, что вы можете избежать " внутри строки как \". Вам также нужно избежать %1, чтобы он был сохранен в значении реестра as-is (берите его так: %%1).
  • Это хорошая идея предоставить вашему пользователю возможность "перерегистрировать" вашу запись в контекстном меню. Без регистрации может быть достигнуто с помощью команды: REG DELETE HKCU\Software\Classes\txtfile\Shell\MyCoolContextMenu /f
  • Опустив /f в конце команд, вы можете запросить "пользователь" (в данном случае ваше приложение) для подтверждения, и в этом случае вам необходимо использовать " getOutputStream() для вывода" Да "для завершения операции. Мы можем избежать этого ненужного взаимодействия, используя флаг силы (/f).

Почти, там!

Находясь на шаге (2), мы должны теперь иметь следующее:

  • Запись контекстного меню, зарегистрированная для наших файлов в категории txtfile (обратите внимание, что она не ограничена .TXT файлами, но применяется ко всем файлам, принадлежащим системе как "txtfiles" ).
  • После нажатия этой записи наше java-приложение должно быть запущено, а метод main() передал массив String, содержащий путь к файлу .TXT с правосторонним щелчком.

Оттуда наше приложение может взять на себя и сделать свою магию:)

Это (почти) все, люди!

Извините, за длинный пост. Надеюсь, это окажется полезным для кого-то. Я попытаюсь добавить демо-код в ближайшее время (не promises хотя;)).

ОБНОВЛЕНИЕ

Демонстрация готова!

licensed under cc by-sa 3.0 with attribution.