我是Java jna API的新手,并且Win32 API方法有问题。我需要从Win32 API获取IShellFolder对象,因为我需要文件的IContextMenu对象。但是,当我从jna ParseDisplayName调用Win32 API方法时,我得到了相同的结果错误:
“该系统找不到指定的文件”。我在下面附加了我的代码。

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


我测试过的每个目录都有相同的错误。
非常感谢你。

最佳答案

欢迎使用StackOverflow!

正如我在评论中提到的,iShellFolder::ParseDisplayNamedocumentation表示第三个参数pszDisplayName是“以显示名称结尾的以空值结尾的Unicode字符串”。在Windows文档中遇到“ Unicode”时,将强制使用“ UTF-16”字符集。

JNA中Windows Unicode字符串的正确映射是WString。不幸的是,JNA将此参数映射为String,它是单字节UTF-8编码(即使Java在内部将字符串存储在UTF-16中)。

您可以通过创建更长的String来解决此问题,该String将UTF-8转换为UTF-16(小字节序)编码(以字节为单位)。之前,我曾发布过一个ASCII解决方案,该方案利用了已知的编码,但是更好的解决方案是使用String的方法将字节提取为UTF-16LE,然后从这些字节中创建一个'\u0000'对象。此代码进行转换:

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


不幸的是,通过检查字节,我不确定它是否包含空终止符,因此您可能希望在执行此操作之前将wstring字符添加到字符串的末尾。

因此,最终您将获得以下内容:

String wstring = new String((test + '\u0000').getBytes("UTF-16LE"));


将传递到需要Unicode字符串的Windows,您已全部完成。

关于java - 使用jna获取IShellFolder,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57460980/

10-13 03:39