Visual Studio 2019 编译 ATL 项目时 propidlbase.idl 重定义错误

Redefinition error in propidlbase.idl when compiling ATL project in Visual Studio 2019

我正在尝试将之前的旧项目从 Visual Studio 2010 迁移到当前版本的 Visual Studio (2019)。 我在微软关于升级的更改说明中,与以前的做法相比,在 VS 2019 中使用 ATL 属性似乎有一些变化。

我能够编译这个项目我在 Visual Studio 2019 年尝试编译这个项目时遇到了一堆重定义错误。

4>64 bit Processing .\vc140.idl
4>vc140.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\shared\wtypes.idl
4>wtypes.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\shared\wtypesbase.idl
4>wtypesbase.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\shared\basetsd.h
4>basetsd.h
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\shared\guiddef.h
4>guiddef.h
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\wincrypt.idl
4>wincrypt.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\prsht.idl
4>prsht.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\objidl.idl
4>objidl.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\unknwn.idl
4>unknwn.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\propidlbase.idl
4>propidlbase.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\oaidl.idl
4>oaidl.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\urlmon.idl
4>urlmon.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\oleidl.idl
4>oleidl.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\servprov.idl
4>servprov.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\msxml.idl
4>msxml.idl
4>64 bit Processing C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\propidl.idl
4>propidl.idl
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(56): error MIDL2003: redefinition : tagVersionedStream
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(60): error MIDL2003: redefinition : PROPSETFLAG_DEFAULT
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(61): error MIDL2003: redefinition : PROPSETFLAG_NONSIMPLE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(62): error MIDL2003: redefinition : PROPSETFLAG_ANSI
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(64): error MIDL2003: redefinition : PROPSETFLAG_UNBUFFERED
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(66): error MIDL2003: redefinition : PROPSETFLAG_CASE_SENSITIVE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(70): error MIDL2003: redefinition : PROPSET_BEHAVIOR_CASE_SENSITIVE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(90): error MIDL2003: redefinition : tagCAC
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(91): error MIDL2003: redefinition : tagCAUB
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(92): error MIDL2003: redefinition : tagCAI
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(93): error MIDL2003: redefinition : tagCAUI
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(94): error MIDL2003: redefinition : tagCAL
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(95): error MIDL2003: redefinition : tagCAUL
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(96): error MIDL2003: redefinition : tagCAFLT
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(97): error MIDL2003: redefinition : tagCADBL
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(98): error MIDL2003: redefinition : tagCACY
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(99): error MIDL2003: redefinition : tagCADATE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(100): error MIDL2003: redefinition : tagCABSTR
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(101): error MIDL2003: redefinition : tagCABSTRBLOB
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(102): error MIDL2003: redefinition : tagCABOOL
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(103): error MIDL2003: redefinition : tagCASCODE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(104): error MIDL2003: redefinition : tagCAPROPVARIANT
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(105): error MIDL2003: redefinition : tagCAH
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(106): error MIDL2003: redefinition : tagCAUH
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(107): error MIDL2003: redefinition : tagCALPSTR
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(108): error MIDL2003: redefinition : tagCALPWSTR
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(109): error MIDL2003: redefinition : tagCAFILETIME
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(110): error MIDL2003: redefinition : tagCACLIPDATA
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(111): error MIDL2003: redefinition : tagCACLSID
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(276): error MIDL2003: redefinition : tag_inner_PROPVARIANT
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(309): error MIDL2003: redefinition : PID_DICTIONARY
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(310): error MIDL2003: redefinition : PID_CODEPAGE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(311): error MIDL2003: redefinition : PID_FIRST_USABLE
4>c:\program files (x86)\windows kits\include.0.17763.0\um\propidlbase.idl(312): error MIDL2003: redefinition : PID_FIRST_NAME_DEFAULT

这是我的 stdafx.h 文件中的内容:

#pragma once
#include <SDKDDKVer.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlwin.h>
#include <atltypes.h>
#include <atlctl.h>
#include <atlhost.h>
#include <comdef.h>

using namespace ATL;

深入研究代码,它看起来像这个 #if 宏是触发包含第二个定义的原因。 来自 propidlbase.idl

cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)")

这是否与项目或编译器设置有关,或者我可能需要另一个#define? 2019年有没有什么特别的东西,比如hidden solution setting需要设置才能在应用项目中使用ATL属性会导致这样的错误?

编辑: 根据西蒙的评论,这是我尝试使用 midl 编译生成的 idl 文件的导入:

import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\wincrypt.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\prsht.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\objidl.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\unknwn.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\propidlbase.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\oaidl.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\urlmon.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\oleidl.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\servprov.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\msxml.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\propidl.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\ocidl.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\comcat.idl";
import "C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.16.27023\atlmfc\include\atliface.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\oleacc.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\shtypes.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\MsHTML.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\dimm.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\dispex.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\shared\dxgitype.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\shared\dxgicommon.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\shared\dxgiformat.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\MsHtmHst.idl";
import "c:\program files (x86)\windows kits\include.0.17763.0\um\docobj.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\ExDisp.idl";
import "C:\Program Files (x86)\Windows Kits\Include.0.17763.0\um\ObjSafe.idl";

根据 Microsoft 文档,错误 MIDL2003 是:您的工具链设置为自动引用系统名称空间中的任何类型。在您的 IDL 文件中,删除 Windows 命名空间的任何 import 指令;您只需要 import 您在项目中定义的任何类型。

您可以编辑 stdafx.h 并参考此 了解更多信息。

#pragma once
#include <sdkddkver.h> //<---- This is the edit.
#include <atlbase.h>
#include <atlcom.h>
#include <atlwin.h>
#include <atltypes.h>
#include <atlctl.h>
#include <atlhost.h>
#include <comdef.h>

using namespace ATL;

您应该从 oa/oc/ole idls 开始,而不是使用直接的 SDK 路径,否则 midl 编译器很可能会混淆。

只需确保 midl.exe 在路径中(就像使用 Visual Studio 2019 developer command prompt 时一样),并像这样使用简化的 .idl:

import "ocidl.idl";
import "oleidl.idl";
import "oaidl.idl";

import "wincrypt.idl";
import "prsht.idl";
import "objidl.idl";
import "unknwn.idl";
import "propidlbase.idl";
import "urlmon.idl";
import "servprov.idl";
import "msxml.idl";
import "comcat.idl";
import "atliface.idl";
import "oleacc.idl";
import "shtypes.idl";
import "MsHTML.idl";
import "dimm.idl";
import "dispex.idl";
import "dxgitype.idl";
import "dxgicommon.idl";
import "dxgiformat.idl";
import "MsHtmHst.idl";
import "docobj.idl";
import "ExDisp.idl";
import "ObjSafe.idl";

@LT21j

在 Visual C++ 历史的某个时刻,库文件 um\propidl.idl 被更改为 #include "propidlbase.idl"。您会在问题的列表片段中看到,vc140.idl 导入 propidlbase.idl,然后几行稍后导入 propidl.idl。这就是触发 MIDL2003 重新定义错误的原因。

您想要的是导入 probidl.idl 而不是 propidlbase.idl - 不能同时导入。

我希望我能告诉您如何更改 auto-generated vc140.idl 中的导入列表,但我不知道该怎么做。相反,这对我有用:

  1. 将生成的 vc140.idl 重命名为更有意义的名称。
  2. 编辑重命名的 .idl 文件:
    • 将 propidl.idl 的导入上移,使其 替换 propidbase.idl 的导入。
    • 在所有导入语句中,去掉 .idl 文件的路径,只留下文件名(例如 import "oaidl.idl)。当您再次升级 Visual C++ 时,您不希望它中断。
    • 出于不相关的原因,我发现我还必须删除 ShObjIdl.idl 的导入;它使用了无效的属性 (disable_consistency_check)。您可能不需要这个,或者您可能会发现建议的解决方法(在项目属性 -> MIDL -> 命令行 -> 其他选项中指定“/target NT60”)可以解决问题。你必须看看哪个适合你。
  3. 将重命名的新 .idl 文件与源代码的其余部分放在同一文件夹中,并将其添加到项目中。 (添加 | 现有项目...)
  4. 告诉链接器不要使用生成的 .idl 文件。解决方案资源管理器 |项目 |属性 |链接器 |嵌入式 IDL |忽略嵌入式 IDL = 是 (/IGNOREIDL)

这对我有用,我希望对你有用。