Ваш вопрос действительно хорош.На дату вашего вопроса класс WindowsShortcut , на который вы ссылаетесь, реализует только код для получения пути к файлу, на который указывает ярлык, но не предоставляет никаких дополнительных данных внутри файла ярлыка.Но это открытый исходный код, поэтому давайте расширим его!
Давайте сначала проведем небольшое исследование
В неофициальной документации Джесси Хагера *1010* мы находим следующее:
______________________________________________________________________________
| |
| **The flags** |
|______________________________________________________________________________|
| | | |
| Bit | Meaning when 1 | Meaning when 0 |
|_____|____________________________________|___________________________________|
| | | |
| 0 | The shell item id list is present. | The shell item id list is absent. |
| 1 | Points to a file or directory. | Points to something else. |
| 2 | Has a description string. | No description string. |
| 3 | Has a relative path string. | No relative path. |
| 4 | Has a working directory. | No working directory. |
| 5 | Has command line arguments. | No command line arguments. |
| 6 | Has a custom icon. | Has the default icon. |
|_____|____________________________________|___________________________________|
Итак, мы знаем, что можем проверить flags byte
на наличие этих дополнительных строк.И у нас уже есть доступ к flags byte
, подготовленному в нашем классе WindowsShortcut
.
Теперь нам нужно только знать, где эти строки хранятся в файле ярлыка.В неофициальной документации мы также находим такую структуру:
File header
Shell item ID list
Item 1
Item 2
etc..
File locator info
Local path
Network path
Description string
Relative path string
Working directory string
Command line string
Icon filename string
Extra stuff
Таким образом, интересующие нас строки приходят сразу после блока File locator info
.Который является опрятным, потому что существующий класс WindowsShortcut
уже анализирует File locator info
, чтобы получить путь к файлу.
Документы также говорят, что каждая строка состоит из длины, заданной как unsigned short
, а затем символов ASCII.Однако, по крайней мере, в Windows10 я столкнулся со строками UTF-16 и соответствующим образом реализовал свой код.
Давайте реализуем!
Мы можем просто добавить еще несколько строк вконец метода parseLink
.
Сначала мы получаем смещение непосредственно после блока File locator info
и называем его next_string_start
, так как теперь оно указывает на первую дополнительную строку:
final int file_location_size = bytesToDword(link, file_start);
int next_string_start = file_start + file_location_size;
Затем мы проверяем флаги для каждой из строк по порядку, и если она существует, мы анализируем ее:
final byte has_description = (byte)0b00000100;
final byte has_relative_path = (byte)0b00001000;
final byte has_working_directory = (byte)0b00010000;
final byte has_command_line_arguments = (byte)0b00100000;
// if description is present, parse it
if ((flags & has_description) > 0) {
final int string_len = bytesToWord(link, next_string_start) * 2; // times 2 because UTF-16
description = getUTF16String(link, next_string_start + 2, string_len);
next_string_start = next_string_start + string_len + 2;
}
// if relative path is present, parse it
if ((flags & has_relative_path) > 0) {
final int string_len = bytesToWord(link, next_string_start) * 2; // times 2 because UTF-16
relative_path = getUTF16String(link, next_string_start + 2, string_len);
next_string_start = next_string_start + string_len + 2;
}
// if working directory is present, parse it
if ((flags & has_working_directory) > 0) {
final int string_len = bytesToWord(link, next_string_start) * 2; // times 2 because UTF-16
working_directory = getUTF16String(link, next_string_start + 2, string_len);
next_string_start = next_string_start + string_len + 2;
}
// if command line arguments are present, parse them
if ((flags & has_command_line_arguments) > 0) {
final int string_len = bytesToWord(link, next_string_start) * 2; // times 2 because UTF-16
command_line_arguments = getUTF16String(link, next_string_start + 2, string_len);
next_string_start = next_string_start + string_len + 2;
}
Метод getUTF16String
просто:
private static String getUTF16String(final byte[] bytes, final int off, final int len) {
return new String(bytes, off, len, StandardCharsets.UTF_16LE);
}
И, наконец, нам нужны члены и получатели для этих новых строк:
private String description;
private String relative_path;
private String working_directory;
private String command_line_arguments;
public String getDescription() {
return description;
}
public String getRelativePath() {
return relative_path;
}
public String getWorkingDirectory() {
return working_directory;
}
public String getCommandLineArguments() {
return command_line_arguments;
}
Я протестировал это под Windows 10, и это сработало как прелесть.
Я сделал запрос на удаление с моими изменениями наОригинальный репо, до этого вы также можете найти полный код здесь .