【问题标题】:Error using C++ COM/IFileDialog in VS Code while the same code works in Visual Studio. Message: 'IID_IFileOpenDialog' was not declared in this scope在 VS Code 中使用 C++ COM/IFileDialog 时出错,而在 Visual Studio 中使用相同的代码。消息:“IID_IFileOpenDialog”未在此范围内声明
【发布时间】:2021-08-26 01:05:34
【问题描述】:

我有 C++ 代码,我试图用组件对象模型的 IFileDialog 打开一个文件选择对话框。该代码可以在 Visual Studio 中运行,但是当我在 VS Code 中键入完全相同的代码时,会出现 2 个错误:

IID_IFileOpenDialog' was not declared in this scope

invalid use of incomplete type 'IFileDialog' {aka 'struct IFileDialog'}

这是在 Visual Studio 中成功加载文件选择对话框的代码:

#include <iostream>
#include <objbase.h>
#include <ShObjIdl.h>

int main()
{
    CoInitializeEx(nullptr, COINIT::COINIT_MULTITHREADED);

    IFileDialog *fileDialog;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, IID_IFileOpenDialog, reinterpret_cast<void**>(&fileDialog));

    if (SUCCEEDED(hr)) {
        fileDialog->AddRef();
        fileDialog->Show(NULL);
    }
    else {
        std::cout << "no" << std::endl;
    }

    CoUninitialize();
}

在 VS Code 中,我使用的是 MinGW/gcc/g++ 编译器(抱歉,我对编译器了解不多,但我认为这三个编译器都能让我的代码运行),而在 Visual Studio 中我不是当然,在绿色播放按钮旁边显示的是本地 Windows 调试器。

是什么导致这个错误只出现在 VS Code 中?

【问题讨论】:

  • 与您的问题无关,但您的fileDialog 变量需要声明为IFileOpenDialog*,因为这是您要求CoCreateInstance() 输出的内容。您应该使用IID_PPV_ARGS() 宏来避免这种不匹配,例如:IFileOpenDialog *fileDialog; HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&amp;fileDialog));
  • gcc 的哪个版本和发行版? (mingw 和 mingw-64 是不同的项目;并且是具有各种不同二进制包的源代码分发)
  • 您的程序在 mingw-w64 目标 x64_64-w64-mingw32,gcc 版本 10.3.0 - MSYS2 中为我正确构建和运行
  • 我确信可以将 VS Code 与 microsoft 编译器一起使用
  • @M.M 我想我用的是mingw-64,我的gcc版本是6.3.0

标签: c++ gcc visual-studio-code com ifiledialog


【解决方案1】:

默认情况下,MinGW 似乎将 NTDDI_VERSION 宏的值设置为 0x05020000 (NTDDI_WS03),这会禁用 shobjidl.h 中的 IFileDialog 定义。宏的值必须至少为 0x06000000 (NTDDI_VISTA) 才能启用定义。此处列出了这些宏的可能值及其含义:

https://docs.microsoft.com/en-us/windows/win32/winprog/using-the-windows-headers

将以下内容放在源文件的开头(在包含之前)应该可以修复编译错误:

#define NTDDI_VERSION 0x0A000006 //NTDDI_WIN10_RS5
#define _WIN32_WINNT 0x0A00 // _WIN32_WINNT_WIN10, the _WIN32_WINNT macro must also be defined when defining NTDDI_VERSION

如果您没有链接所需的库,可能仍然会出现链接错误。您列出的程序需要 ole32.dll 和 uuid.dll,因此编译命令如下所示:

x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ program.cpp -lole32 -luuid

MSDN 并不总是记录需要链接哪些 DLL 才能访问哪些符号(或者至少,我在搜索它时找不到信息),但是一种快速而肮脏的方法是在 MinGW 的 lib 目录中使用 grep。例如,当找到提供符号“CLSID_FileOpenDialog”的库时:

$ grep -r CLSID_FileOpenDialog /usr/x86_64-w64-mingw32/lib
Binary file /usr/x86_64-w64-mingw32/lib/libuuid.a matches

所以我们知道要在编译命令中添加“-luuid”

【讨论】:

  • 我建议在构建系统中包含定义可能是个好主意,以避免不同的翻译单元看到不同版本的 windows 标头,这可能会导致棘手的问题
  • @Sarah D. 非常感谢,这解决了它,我现在可以在 VS Code 中使用 COM,你真是个天才。
  • 补充我的其他评论,我对编译器和像这样的高级计算机知识还不是很了解,所以我无法做到你在这里描述的所有事情,但我能做到的事情找出解决问题。对于遇到此问题的任何人,这就是我所做的:就像 Sarah 所说,我将这些 #define 语句添加到源文件的顶部。然后我在我的tasks.json的args部分添加了“-lole32”和“-luuid”,程序就开始工作了。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2016-07-08
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
  • 1970-01-01
  • 2018-03-01
相关资源
最近更新 更多