使用 jna 获取 IShellFolder
Get IShellFolder with jna
我是 java jna API 的新手,我遇到了 Win32 API 方法的问题。我需要从 Win32 API 获取 IShellFolder 对象,因为我需要文件的 IContextMenu 对象。但是当我从 jna ParseDisplayName 调用 Win32 API 方法时,我得到了相同的结果错误:
"The system cannot find the file specified"。我在下面附上了我的代码。
String directory = "c:\Users";
IntByReference pchEaten = new IntByReference();
pchEaten.setValue(0);
PointerByReference ppidl = new PointerByReference();
IntByReference pdwAttributes = new IntByReference();
pdwAttributes.setValue(0);
PointerByReference desktopFolder = new PointerByReference();
WinNT.HRESULT hResult = Shell32.INSTANCE.SHGetDesktopFolder(desktopFolder);
IShellFolder shellFolder = IShellFolder.Converter.PointerToIShellFolder(desktopFolder);
if (COMUtils.SUCCEEDED(hResult) && shellFolder != null) {
hResult = shellFolder.ParseDisplayName(new WinDef.HWND(Pointer.NULL), Pointer.NULL, directory, pchEaten, ppidl, pdwAttributes);
if (COMUtils.SUCCEEDED(hResult)) {
return true;
}
else {
return false;
}
}
else {
return false;
}
我测试过的每个目录都有同样的错误。
非常感谢。
欢迎使用 Whosebug!
正如我在评论中提到的,iShellFolder::ParseDisplayName
的 documentation 表示第三个参数 pszDisplayName
是 "A null-terminated Unicode string with the display name." 当在 Windows 文档,"UTF-16" 字符集已实现。
JNA 中 Windows Unicode 字符串的正确映射是 WString
。不幸的是,JNA 已将此参数映射为单字节 UTF-8 编码的 String
(即使 Java 在内部以 UTF-16 存储字符串)。
您可以通过创建更长的 String
将 UTF-8 转换为 UTF-16(小端)编码(以字节为单位)来解决此问题。我之前发布了一个利用其已知编码的 ASCII 解决方案,但更好的解决方案是使用 String 的方法将字节提取为 UTF-16LE,然后从这些字节中创建一个 String
对象。此代码进行转换:
String test = "müller_test.pdf";
byte[] utf16 = test.getBytes("UTF-16LE");
System.out.println("utf16 that we need to pass:\n" + Arrays.toString(utf16));
String wString = new String(utf16);
System.out.println("Pass this to Windows:\n" + wString);
产生此输出:
utf16 (little endian) that we need to pass:
[99, 0, 58, 0, 92, 0, 85, 0, 115, 0, 101, 0, 114, 0, 115, 0]
Pass this to Windows:
m � l l e r _ t e s t . p d f
不幸的是,通过检查字节我不确定它是否包含空终止符,因此您可能希望在执行此操作之前将 '\u0000'
字符添加到字符串的末尾。
所以最终你会得到这样的一行:
String wstring = new String((test + '\u0000').getBytes("UTF-16LE"));
将 wstring
传递给 Windows 它需要 Unicode 字符串的地方,一切就绪。
我是 java jna API 的新手,我遇到了 Win32 API 方法的问题。我需要从 Win32 API 获取 IShellFolder 对象,因为我需要文件的 IContextMenu 对象。但是当我从 jna ParseDisplayName 调用 Win32 API 方法时,我得到了相同的结果错误: "The system cannot find the file specified"。我在下面附上了我的代码。
String directory = "c:\Users";
IntByReference pchEaten = new IntByReference();
pchEaten.setValue(0);
PointerByReference ppidl = new PointerByReference();
IntByReference pdwAttributes = new IntByReference();
pdwAttributes.setValue(0);
PointerByReference desktopFolder = new PointerByReference();
WinNT.HRESULT hResult = Shell32.INSTANCE.SHGetDesktopFolder(desktopFolder);
IShellFolder shellFolder = IShellFolder.Converter.PointerToIShellFolder(desktopFolder);
if (COMUtils.SUCCEEDED(hResult) && shellFolder != null) {
hResult = shellFolder.ParseDisplayName(new WinDef.HWND(Pointer.NULL), Pointer.NULL, directory, pchEaten, ppidl, pdwAttributes);
if (COMUtils.SUCCEEDED(hResult)) {
return true;
}
else {
return false;
}
}
else {
return false;
}
我测试过的每个目录都有同样的错误。 非常感谢。
欢迎使用 Whosebug!
正如我在评论中提到的,iShellFolder::ParseDisplayName
的 documentation 表示第三个参数 pszDisplayName
是 "A null-terminated Unicode string with the display name." 当在 Windows 文档,"UTF-16" 字符集已实现。
JNA 中 Windows Unicode 字符串的正确映射是 WString
。不幸的是,JNA 已将此参数映射为单字节 UTF-8 编码的 String
(即使 Java 在内部以 UTF-16 存储字符串)。
您可以通过创建更长的 String
将 UTF-8 转换为 UTF-16(小端)编码(以字节为单位)来解决此问题。我之前发布了一个利用其已知编码的 ASCII 解决方案,但更好的解决方案是使用 String 的方法将字节提取为 UTF-16LE,然后从这些字节中创建一个 String
对象。此代码进行转换:
String test = "müller_test.pdf";
byte[] utf16 = test.getBytes("UTF-16LE");
System.out.println("utf16 that we need to pass:\n" + Arrays.toString(utf16));
String wString = new String(utf16);
System.out.println("Pass this to Windows:\n" + wString);
产生此输出:
utf16 (little endian) that we need to pass:
[99, 0, 58, 0, 92, 0, 85, 0, 115, 0, 101, 0, 114, 0, 115, 0]
Pass this to Windows:
m � l l e r _ t e s t . p d f
不幸的是,通过检查字节我不确定它是否包含空终止符,因此您可能希望在执行此操作之前将 '\u0000'
字符添加到字符串的末尾。
所以最终你会得到这样的一行:
String wstring = new String((test + '\u0000').getBytes("UTF-16LE"));
将 wstring
传递给 Windows 它需要 Unicode 字符串的地方,一切就绪。