1

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?

Tobi
  • 2,591
  • 15
  • 34
  • 1
    Not related to your problem, but your `fileDialog` variable needs to be declared as `IFileOpenDialog*`, since that is what you are asking `CoCreateInstance()` to output. You should use the [`IID_PPV_ARGS()`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-iid_ppv_args) macro to avoid this kind of mismatch, eg: `IFileOpenDialog *fileDialog; HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&fileDialog));` – Remy Lebeau Jun 09 '21 at 04:36
  • which version and distribution of gcc? (mingw and mingw-64 are different projects; and are source distributions with various different binary packages existing) – M.M Jun 09 '21 at 04:49
  • Your program builds and runs correctly for me in mingw-w64 target x64_64-w64-mingw32, gcc version 10.3.0 - MSYS2 – M.M Jun 09 '21 at 04:51
  • I'm sure it is possible to use VS Code with the microsoft compiler – M.M Jun 09 '21 at 04:52
  • @M.M I think I'm using mingw-64, and my gcc version is 6.3.0 – DoinSomeCodeEre Jun 09 '21 at 04:55
  • That's pretty old, maybe your version doesn't have correct headers for IFileOpenDalog – M.M Jun 09 '21 at 04:55
  • I had lots of issues developing on Windows with mingw/gcc environements (there are many...) that come with rewritten header files (not the Windows SDK) missing lots of information. The problem is not the compiler, it's the header file, or the whole dev environment. PS: you don't need to call `AddRef`, it's implicit in `CoCreateInstance`, but you do need to call `Release` after you used the reference (=>Here you have 2 missing Release) – Simon Mourier Jun 09 '21 at 06:34

1 Answers1

2

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

Sarah D.
  • 36
  • 2
  • I'd suggest probably a good idea to include the defines in the build system in order to avoid different translation units seeing different versions of windows header, which could lead to tricky problems – M.M Aug 01 '21 at 21:12
  • @Sarah D. Thank you so much, this solved it and I can now use the COM in VS Code, you're a genius. – DoinSomeCodeEre Aug 03 '21 at 18:55
  • To add to my other comment, I'm still not super knowledgeable on compilers and advanced computer stuff like this, so I wasn't able to do everything you described here, but the things I was able to figure out fixed the problem. To anyone who has this problem, here's what I did: Like Sarah said, I added those #define statements to the top of my source file. Then I just added "-lole32" and "-luuid" to the args section of my tasks.json, and the program started working. Thanks again! – DoinSomeCodeEre Aug 03 '21 at 18:59