SHChangeNotifyRegister с QT / MinGW 4.8 не удается связать


Я пытаюсь реализовать функцию, при которой запоминающие устройства USB автоматически определяются моей программой.

Я понимаю, что мне нужно слушать WM_DEVICECHANGE, и сделал это с помощью QAbstractNativeEventFilter, но это не ловит конкретный случай, который является SD-карта вставляется или удаляется из считывателя (или в моем конкретном случае, нажав кнопку "Включить mass storage" на моем телефоне).

После некоторого гугления я нашел этот пост: обнаружение вставки носителей в диск с помощью сообщений windows который точно описывает, что мне нужно, который использует SHCNE_MEDIAINSERTED и SHCNE_MEDIAREMOVED.

Моя проблема заключается в том, что мой компоновщик не может найти SHChangeNotifyRegister. Внутри Qt Creator я получаю объявления завершения кода для slobj.h, но при компиляции я получаю следующее:

error: undefined reference to `_imp__SHChangeNotifyRegister@24'

Затем ld завершается ошибкой с кодом выхода 1.

Я в недоумении относительно того, что компоновщик не может найти, включенные прекрасно внутри QtCreator-так что он не может найти shell32.dll? Я бегу mingw4.8 32bit это случай, когда он не может использовать библиотеку dll, скомпилированную с другим компилятором? Я также попытался добавить win32: LIBS += -lshell32 в свой файл. pro безрезультатно, а также добавил папку lib SDK для windows 7 в переменную path.

Мой код выглядит следующим образом (обратите внимание, что я на 100% бесполезен с winapi, так что этот код, вероятно, массово сломан, поскольку я был в середине работы с ним):

MainWindow w(deviceMgr);
w.show();

int sources = 0x0001 | 0x0002 | 0x8000; // Interupt, Shell, New Delivery Missing Defs
LONG events = SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED;

PIDLIST_ABSOLUTE pidl;

SHGetFolderLocation((HWND) w.winId(), CSIDL_DRIVES, NULL, 0, &pidl);

SHChangeNotifyEntry entries[] = { pidl, false };

ULONG code = SHChangeNotifyRegister(
    (HWND) w.winId(),
    sources,
    events,
    WM_APP + 1,
    ARRAYSIZE(entries),
    entries
);
Приветствуются также комментарии, которые могли бы помочь мне лучше сформулировать этот вопрос.

Обновление:

Вслед За Кэри и предложения Майклса в заметках я выяснил несколько вещей:

  • я не использую shell32.lib из Windows SDK, потому что я думаю, что это для MSVC.
  • Mingw связывает против своего собственного shell32.a

  • Используя objdump -x shell32.a из моего распределения mingw, я не могу найти ссылку на SHChangeNotifyRegister.

  • Используя objdump -x shell32.lib на shell32.lib из Windows SDK я могу найти строку:

    [  3](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 __imp__SHChangeNotifyRegister@24
    

Это заставляет меня поверьте, что шелл32.дистрибутив с mingw 4.8 является неполным и поэтому моя программа не будет связываться.

Поэтому я думаю, что изучу либо более свежую версию mingw , если она существует, либо связывание с WindowsSDK с mingw, что, по моему мнению, невозможно, либо использование MSVC для моих сборок windows.

Поэтому я думаю, что ответ на мой вопрос таков: "это не связано, потому что ваш shell32.a не содержит всего, что находится в .ч"?

Ответ:

Оказывается, mingw может использовать определенный msvc .файлы lib. Так что на этот раз я правильно подключился к версии SHELL32 для Windows SDK.Либ и все, кажется, работает. Короче говоря, это нужно было добавить в мой файл .pro:

win32: LIBS += -L"C:/Path/To/Microsoft/Microsoft SDKs/Windows/v7.1/Lib/" -lshell32
2 3

2 ответа:

Чтобы я мог принять ответ на этот вопрос, я опубликую решение здесь.

Чтение комментариев Кэри и Майкла по этому вопросу дало мне ключ к разгадке того, что было неправильно.

Похоже, что либо вы не связываетесь с Shell32.Либ по какой-то причине или что ваш Shell32.lib не экспортирует функцию _SHChangeNotifyRegister@24. Попробуйте найти Shell32.lib файл, тип " dumpbin / exports shell32.lib " в командной строке и посмотрите, если _SHChangeNotifyRegister@24 функция экспортируется

По существу shell32.a, что mingw связывал против отсутствовало определение SHChangeNotifyRegister (версия mingw shlobj.h имела это объявление) - вы можете прочитать, как я пришел к этому выводу в обновлениях вопроса.

Для исправления решения я использовал копию shell32.lib из пакета SDK для Windows, который у меня лежал - я думаю, что это можно найти здесь. К счастью, мингв мог связать это .файл lib.

Чтобы связать новый shell32.lib с моим Qt Qbuild .pro файлом I используется следующее:

win32: LIBS += -L"C:/Path/To/Microsoft/Microsoft SDKs/Windows/v7.1/Lib/" -lshell32

Я получал аналогичную ошибку при попытке скомпилировать приложение. Я хотел построить Qt Creator с помощью инструментария MSVC 2013. У меня было LIBS += -ladvapi32 в моем файле .pro, но я все еще получал:

FilePathUtilities.obj : error LNK2019: 
unresolved external symbol __imp_ShellExecuteExW 
referenced in function "void __cdecl FileShowInExplorer(class CStr const &,int)"

Проблема оказалась простой: я строил с помощью инструментария x64 MSVC вместо 32-битного инструментария!

Не знаю почему, я не c++ dev, но похоже, что 32-и 64-битные идентификаторы не идентичны:

/* 32 BIT LIBRARY */
/c/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib
$ "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\dumpbin.exe" -exports shell32.lib | grep ShellEx
                  _WOWShellExecute@28
                  _ShellExecuteW@24
                  _ShellExecuteExW@4
                  _ShellExecuteExA@4
                  _ShellExecuteEx@4
                  _ShellExecuteA@24


/* 64 BIT LIBRARY */
/c/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib/x64
$ "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\x86_amd64\dumpbin.exe" -exports shell32.lib | grep ShellEx
                  ShellExecuteA
                  ShellExecuteEx
                  ShellExecuteExA
                  ShellExecuteExW
                  ShellExecuteW
                  WOWShellExecute