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.