简体   繁体   中英

Why does regsvr32 fail after upgrading an ATL project to VS2015.1?

In my current project I have multiple ATL projects that depend on each other. One of them is called "Common" and defines a trace category, other projects might use to print out trace information.

I defined the category from the IDL file like so:

cpp_quote("static ATL::CTraceCategory DATA_LAYER(_T(\"Data Layer\"), 1);")

Basically this translates to the following definition inside the common header file, other projects include to get informed about the interfaces of the "Common" project.

static ATL::CTraceCategory DATA_LAYER(_T("Data Layer"), 1);

Now since Visual Studio 2013 there appears to be a change in how tracing works.

This does cause source-breaking changes in some uses of the ATL::CTraceCategory class, which will require changes in source code when migrating to Visual Studio 2013.

And indeed, I had to change the line above by removing the second parameter:

cpp_quote("static ATL::CTraceCategory DATA_LAYER(_T(\"Data Layer\"));")

Now everything builds again, but the problem raises as soon as I try to rebuild any project that uses the trace category. After the build successfully finished, the compiler automatically registers the component. And during regsvr32 /s "C:\\...\\Common.dll" I always receive an debug assertation like this:

Microsoft Visual C++ Runtime Library

Debug Assertion Failed!

Program: ...\\x64\\Debug\\Common.dll

File: c:\\program files (x86)\\microsoft visual studio 14.0\\vc\\atlmfc\\include\\atltrace.h

Line: 337

Expression: false && "Too many categories defined"

This also happens when I try to register the component manually. Only projects that do not depend on the common project and therefor not use any trace category are registered successfully.

Does anybody have a solution for this? I would also accept a solution that shows another way of tracing in ATL, since there does not appear to be any difference to using DebugOutputString instead (If I understood the linked blog correctly).

Okay, I finally figured this out. The problem was related to the declaration of the trace category as static . I have no idea why this built in previous versions of Visual Studio. Anyway, here's the fix: First of all, I changed the definition of the trace category inside my Common.idl file:

cpp_quote("#ifdef DEFINE_EXPORTS")
cpp_quote("__declspec(dllexport) extern ATL::CTraceCategory DATA_LAYER;")
cpp_quote("#else // DEFINE_EXPORTS")
cpp_quote("__declspec(dllimport) ATL::CTraceCategory DATA_LAYER;")
cpp_quote("#endif // DEFINE_EXPORTS")

As you can see, the trace category now exports to the library, if DEFINE_EXPORTS is defined, which is true for the common project. All projects referencing this library are importing the definition (by including Common.h , which get's created from the idl file). If you define the trace category as static, each library defines a category on it's own. I think that was the cause for the error I was facing.

Now inside the dllmain.cpp file of the common project I define the trace categories:

#if (_MSC_VER >= 1800)
ATL::CTraceCategory DATA_LAYER(_T("Data Layer"));
#else
ATL::CTraceCategory DATA_LAYER(_T("Data Layer"), 1);
#endif

Note that the code switches between two constructors based on the VC++ version it is compiled with. It should be possible to get rid of this by using the CTraceCategoryEx template, but I stick to this method for now.

Finally all I had to do was adding the Common.lib reference to the Additional Dependencies of the projects referencing it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM