SHChangeNotifyRegister与QT / MinGW 4.8无法链接

时间:2013-08-04 22:06:24

标签: c++ qt winapi mingw

我正在尝试实现一项功能,即我的程序会自动检测USB存储设备。

我知道我需要收听WM_DEVICECHANGE,并且已经使用了QAbstractNativeEventFilter,但这并没有抓住特定的案例,即从读卡器中插入或移除的SD卡(或在我的特定情况下按下手机上的“打开大容量存储空间”按钮。

通过一些谷歌搜索,我发现了这篇帖子:Detect insertion of media into a drive using windows messages,它准确描述了我需要使用SHCNE_MEDIAINSERTEDSHCNE_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文件中无效,并且还将Windows 7 SDK的lib文件夹添加到我的路径变量中。

我的代码如下(注意我对winapi 100%没用,所以这个代码可能会因为我正在修补它而大量破坏):

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

评论也欢迎这可能有助于我更好地阐述这个问题。

更新

根据Carey和Michaels在笔记中的建议我已经找到了一些东西:

  • 我没有使用Windows SDK中的shell32.lib,因为我认为这是针对MSVC的。
  • mingw链接自己的shell32.a

  • 使用了我的mingw发行版中的objdump -x shell32.a,我找不到对SHChangeNotifyRegister的引用。

  • 在Windows SDK的objdump -x shell32.lib上使用shell32.lib我可以找到该行:

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

这让我相信与mingw 4.8一起发布的shell32.a是不完整的,因此我的程序不会链接。

所以我想我将探索更新版本的mingw 如果存在或者使用mingw链接WindowsSDK,我认为这是不可能的或使用MSVC进行我的Windows版本。

因此,我认为我的问题的答案是:“它没有链接,因为你的shell32.a不包含.h中的所有内容”?

解答:

原来mingw可以使用某些msvc .lib文件。所以这一次我正确地链接到了Windows SDK版本的shell32.lib,一切似乎都有效。简而言之,这需要添加到我的.pro文件中:

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

2 个答案:

答案 0 :(得分:2)

所以我可以接受这个问题的答案,我会在这里发布解决方案。

阅读凯里和迈克尔对这个问题的评论给了我一个关于错误的线索。

  

听起来你要么因为某种原因没有链接到Shell32.lib,要么你的Shell32.lib没有导出_SHChangeNotifyRegister @ 24函数。尝试查找Shell32.lib文件,在命令提示符下键入“dumpbin / exports shell32.lib”,查看_SHChangeNotifyRegister @ 24函数是否已导出

基本上,mingw链接的shell32.a缺少SHChangeNotifyRegister的定义(shlobj.h的mingw版本有此声明) - 你可以阅读我是如何得出这个结论的更新问题。

要修复该解决方案,我使用了我已经存在的Windows SDK中的shell32.lib副本 - 我认为可以找到here。幸运的是,mingw可以链接.lib文件。

要将新的shell32.lib与我的QT Qbuild .pro文件相关联,我使用了以下内容:

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

答案 1 :(得分:0)

我在尝试编译应用时遇到了类似的错误。我希望使用MSVC 2013工具包构建Qt Creator。我的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 ++开发人员,但看起来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