你的问题真的很好。截至您提出问题的日期,您引用的WindowsShortcut 类仅实现代码以获取快捷方式指向的文件的路径,但不提供快捷方式文件内的任何进一步数据。但它是开源的,所以让我们扩展它吧!
让我们先做一些研究
在 Jesse Hager 的非官方文档中,我们发现:
______________________________________________________________________________
| |
| **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 下测试了它,它就像一个魅力。
我对原始存储库的更改提出了拉取请求,在此之前您还可以在此处找到完整的代码。