c++gccvisual-studio-codecomifiledialog

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


I have C++ code where I'm trying to open a file select dialog with the Component Object Model's IFileDialog. The code works in Visual Studio but when I type the exact same code in VS Code, there are 2 errors:

IID_IFileOpenDialog' was not declared in this scope

and

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

Here is the code which successfully loads the file select dialog in 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();
}

In VS Code, I am using the MinGW/gcc/g++ compiler (sorry, I don't know too much about compilers but I think all of those three make my code run), and in Visual Studio I'm not sure, next to the green play button it says Local Windows Debugger.

What causes this error to appear only in VS Code?


Solution

  • By default, it looks like MinGW sets the value of the NTDDI_VERSION macro to 0x05020000 (NTDDI_WS03), which disables the IFileDialog definitions in shobjidl.h. The value of the macro must be at least 0x06000000 (NTDDI_VISTA) to enable the definitions. Possible values of these macros and their meanings are listed here:

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

    Putting the following at the beginning of your source file (before the includes) should fix the compilation errors:

    #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
    

    There may still be link errors if you you are not linking the needed libraries. The program you listed requires ole32.dll and uuid.dll, so the command to compile will look like this:

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

    MSDN doesn't always document which DLLs need to be linked to access which symbols (or at least, I had trouble finding the information when I searched for it), but a quick-and-dirty way of doing it is to use grep in MinGW's lib directory. For example, when finding the library which provides the symbol "CLSID_FileOpenDialog":

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

    So we know to add "-luuid" to the compile command