SHChangeNotifyRegister与QT/MinGW 4.8无法链接

3

我正在尝试实现一个功能,即通过我的程序自动检测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一点也不了解,所以这段代码可能存在严重问题,因为我正在进行修改):
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 在注释中的建议,我已经弄清楚了一些事情:

  • I'm not using the shell32.lib from the Windows SDK because I think that is for MSVC.
  • mingw links against its own shell32.a

  • Having used objdump -x shell32.a from my mingw distribution I can find no reference to SHChangeNotifyRegister.

  • Using objdump -x shell32.lib on the shell32.lib from the windows SDK I can find the line:

    [  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

类似这样的链接错误通常意味着您在函数参数、返回类型或调用约定方面出现了问题。 - Carey Gregory
1
看起来要么是由于某些原因你没有链接到Shell32.lib,要么是你的Shell32.lib没有导出_SHChangeNotifyRegister@24函数。尝试找到Shell32.lib文件,在命令提示符下键入“dumpbin /exports shell32.lib”,查看是否导出_SHChangeNotifyRegister@24函数。 - Jabberwocky
好的,我认为那些回复让我更接近理解正在发生的事情。我将更新问题,也许你们其中之一可以将你的信息放在答案中,因为我想我会接受一个答案。如果我弄错了,请在留言中说明 :) - Kasheen
2个回答

2
为了能在这个问题上接受答案,我会在这里发布解决方案。
阅读Carey和Michael在问题上的评论,给了我一个线索,知道了问题出在哪里。
引用:
听起来要么你由于某些原因没有链接到Shell32.lib,要么你的Shell32.lib没有导出_SHChangeNotifyRegister@24函数。尝试找到Shell32.lib文件,在命令提示符下键入“dumpbin /exports shell32.lib”,看看是否导出_SHChangeNotifyRegister@24函数。
本质上,mingw链接的shell32.a缺少SHChangeNotifyRegister的定义(mingw版本的shlobj.h具有此声明)-您可以在问题的更新中阅读我得出结论的方式。
要解决这个问题,我使用了一份我拥有的Windows SDK中的shell32.lib副本-我认为这可以在这里找到。幸运的是,mingw可以链接那个.lib文件。
为了将新的shell32.lib与我的QT Qbuild .pro文件链接起来,我使用了以下内容:
win32: LIBS += -L"C:/Path/To/Microsoft/Microsoft SDKs/Windows/v7.1/Lib/" -lshell32

0

我在尝试编译应用程序时遇到了类似的错误。我想让Qt Creator使用MSVC 2013工具包进行构建。我在我的.pro文件中添加了LIBS += -ladvapi32,但仍然出现以下错误:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接