Используйте SHGetFileInfo в Java с JNA - PullRequest
2 голосов
/ 17 марта 2019

Я попытался перевести функцию SHGetFileInfo из Shell32 в Java с JNA и использовал код C # и this в качестве ссылки

В то время как в коде C # psfi.iIcon равен 432 в моем переведенном Javaкод psfi.iIcon равен 0. Если я прав, то для одного и того же файла они должны быть одинаковыми независимо от того, какой язык я использую, не так ли?

Мой код Java:

public static void main(String[] args) {
    String path = "[PATH_TO_EXE]\\test.exe"; //Off course in my code I used the real path

    SHFILEINFO sfi = new SHFILEINFO();
    DWORD_PTR i = Shell32.INSTANCE.SHGetFileInfo(path, 0, sfi, sfi.size(), SHGFI.SysIconIndex);

    System.out.println(sfi.iIcon); //<-- Prints 0, should print 432
}

public static class SHGFI {
    static final int SysIconIndex = 0x000004000;
    static final int LargeIcon = 0x000000000;
    static final int UseFileAttributes = 0x000000010;
}

public interface Shell32 extends StdCallLibrary {
    Shell32 INSTANCE = Native.loadLibrary("shell32", Shell32.class, W32APIOptions.UNICODE_OPTIONS);
    DWORD_PTR SHGetFileInfo(String pszPath, int dwFileAttributes, SHFILEINFO psfi, int cbFileInfo, int uFlags);
}

public static class SHFILEINFO extends Structure {
    public HICON hIcon;
    public int iIcon;
    public DWORD dwAttributes;
    public char[] szDisplayName = new char[260];
    public char[] szTypeName = new char[80];

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("hIcon", "iIcon", "dwAttributes", "szDisplayName", "szTypeName");
    }
}
* 1009Есть ли что-то фундаментальное, что я сделал не так?Я новичок в функциях JNA и Windows

1 Ответ

3 голосов
/ 17 марта 2019

В разделе Замечания есть эта часть информации, которая может быть источником вашей проблемы для imho

Вы должны инициализировать объектную модель компонентов (COM) с CoInitialize или OleInitialize до звонка SHGetFileInfo.

Это довольно простой вызов

CoInitialize(null);

Как указал Даниэль Уиддис в комментариях, согласно документации

Новые приложения должны вызывать CoInitializeEx вместо CoInitialize

И

Чтобы корректно закрыть библиотеку COM, каждый успешный вызов CoInitialize или CoInitializeEx, включая те, которые возвращают S_FALSE, должен быть сбалансирован соответствующим вызовом на CoUninitialize

Пример * +1034 *

CoInitializeEx(null, 0);
CoUninitialize();
...