3

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

我知道我需要听WM_DEVICECHANGE,并且已经使用了 aQAbstractNativeEventFilter但这并没有捕捉到特定情况,即从读卡器中插入或移除 SD 卡(或者在我的特定情况下按下“打开大容量存储”按钮在我的手机上)。

在一些谷歌搜索后,我发现了这篇文章:使用 Windows 消息检测媒体插入驱动器,该消息准确描述了我需要什么,它使用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 文件中无济于事,并将libWindows 7 SDK 的文件夹添加到我的路径变量中。

我的代码如下(请注意,我对 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 的引用。

  • objdump -x shell32.lib在windows SDK 上使用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,我认为这是不可能的,或者在我的 Windows 构建中使用 MSVC。

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

回答:

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

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

2 回答 2

2

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

阅读 Carey 和 Michael 对这个问题的评论让我知道出了什么问题。

听起来您出于某种原因没有与 Shell32.lib 链接,或者您的 Shell32.lib 没有导出 _SHChangeNotifyRegister@24 函数。尝试找到 Shell32.lib 文件,在命令提示符处键入“dumpbin /exports shell32.lib”并查看是否导出了 _SHChangeNotifyRegister@24 函数

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

为了解决这个问题,我使用了shell32.lib一个 Windows SDK 的副本——我认为这可以在这里找到。幸运的是,mingw 可以链接那个 .lib 文件。

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

win32: LIBS += -L"C:/Path/To/Microsoft/Microsoft SDKs/Windows/v7.1/Lib/" -lshell32
于 2013-08-06T20:17:16.297 回答
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
于 2014-09-27T00:06:42.093 回答