Similar Threads
1. Injecting C# (COMVisible) code into a COM-object
2. CoCreateObject of C# ComVisible object from C++ Crashes
I have three DLL projects, all compiled from Visual Studio 2003
projects.
One is an ATL C++ project, no managed code, which just defines a bunch
of __interfaces for IDL generation. The DLL it generates is not really
useful for anything, just the associated TLB.
The second is C#. It consumes the TLB generated by the first project
(as a "COM reference" in Visual Studio, so it's using an auto-generated
COM wrapper). It contains two classes that implement interfaces
declared in the first DLL and are marked ComVisible(true), and with
valid ProgId and Guid attributes.
The third is another ATL C++ project. It consumes the first project's
__interface definitions through #include, and defines a few coclasses
to implement some of the interfaces. It consumes the second project's
classes through an #import of the TLB generated when the second project
is compiled.
The goal is to create instances of the two C# classes through COM
(using CoCreateInstance) and then make method calls on them. Simple
enough...
The whole shebang is hosted by a 3rd party executable for which I have
no source code or debug build.
I really want to debug in mixed mode, so I can step from C++ to C# and
back. When I try that, though, it runs really slow, unusably so. The
setup to get to the point where I try to call CoCreateInstance takes
closer to 10 minutes than the 10 seconds it should... Then, when I get
to that point, the CoCreateInstance call causes Visual Studio to crash
hard. The "This program has done something incredibly stupid and
terminated, would you like to send MS an error report?" box comes up.
That happens whether I try to step over the statement, or set a
breakpoint past the statement and let it run past (if that matters; I
know those two do subtly different things).
When I debug in native mode, things seem to work mostly OK, but of
course I can't debug the C# code. CoCreateInstance doesn't crash, and
I can see through other evidence (trace statements) that my C# gets
created and later method invocations into the C# work as expected.
When I debug in managed mode, CoCreateInstance crashes hard again.
I've got the debugger watching for every kind of exception it's able to
(all managed, all unmanaged, all native run-time and all Win32), and
none of them catch whatever it is that happens. I've seen this
behavior before when a stack overflow occurs, but I suspect that's not
what's happening here, unless CoCreateInstance can internally cause a
stack overflow somehow? Unlike mixed mode debugging, in managed mode,
the process crashes without taking Visual Studio with it. Instead,
Visual Studio silently drops from debugging to editing mode as if the
process had exited normally, with no trace statements, error messages,
or exception notifications.
This little 5 hour COM interop task has turned into an all (holiday)
weekend cluster. Any help is appreciated, both with the
CoCreateInstance call and with suggestions for speeding up mixed-mode
debugging, if possible.
(NOTE: I originally tried using a mixed-mode DLL instead of COM to get
the C++ and C# to talk: the DLL had a dynamically-loadable C interface
on one end and used IJW to instantiate and make method calls on the C#.
However, I only got that to work when the host EXE was managed; when
using the unmanaged host EXE (the 3rd party one mentioned earlier), I
got mysterious exceptions deep down in mscorwrks, so I decided to fall
back to a COM implementation, since I understood what was going on with
COM a little better...)
Ok, selected code snippets:
In DLL 1:
(In AMSConduitCOM.h)
[
object,
uuid("50D5CECC-E3ED-4E21-8C68-007102F475AE"),
dual,
pointer_default(unique),
library_block
]
__interface IUserNotifier : public IDispatch
{
[ id(0), propget ] HRESULT IProgressSink(
[out, retval] IProgressSink** pProgSink
);
[ id(1) ] HRESULT Open([in] BSTR appFolder, [in] BSTR clientId);
[ id(2) ] HRESULT Notify([in] BSTR title, [in] BSTR msg, [in] int
msTimeout);
[ id(3) ] HRESULT Dispose();
};
In DLL 2:
(AMSConduitCOM is the namespace into which the TLB wrapper generator
places the stuff it reads from DLL 1's TLB).
[ ComVisible(true) ]
[ ProgId("OMITTED.UserNotifier") ]
[ Guid("2AB345A1-C156-437C-831F-EF31862790B7") ]
public class AMSConduitUserNotifier : AMSConduitCOM.IUserNotifier
{
public AMSConduitUserNotifier()
{
// Intentionally Empty
}
...remaining implementation elided...
}
In DLL 3:
#include "AMSConduitCOM.h"
// Create a suitable environment for bringing in our COM wrappers.
#undef GetMessage
#if defined(_DEBUG)
# import "../OMITTED/bin/Debug/OMITTED.tlb" rename_namespace("amsdsl")
auto_search
#else
# import "../OMITTED/bin/Release/OMITTED.tlb"
rename_namespace("amsdsl") auto_search
#endif
...
IUserNotifier* m_pUserNotifier;
LogManager::Log("CALL: UserNotifier->CreateInstance");
HRESULT hr = CoCreateInstance(
__uuidof(amsdsl::AMSConduitUserNotifier), NULL, CLSCTX_ALL,
__uuidof(::IUserNotifier), (void**) &m_pData->m_pUserNotifier
);
if(!SUCCEEDED(hr))
{
LogManager::Log("FAIL: UserNotifier->CreateInstance");
delete m_pData;
throw COMError(ThrownFromHere("CreateInstance(UserNotifier)"), hr);
}
LogManager::Log("OK: UserNotifier->CreateInstance");
And of course, the crash happens at the CoCreateInstance call just
above. To clarify, when the crash happens, none of the logging stuff
after the call happens, b/c the crash brings the process down hard;
CoCreateInstance never returns.
3. ComVisible and generics - CSharp/C#
4. ComVisible object won't terminate if PerformanceCounter created internally
5. ComVisible(false) doesn't work as expected - CSharp/C#
6. ComVisible query
I have one resource telling me that if I want to expose just 4 out of 10
methods in my class to COM I simply apply the ComVisible attribute to the
class and set it to false, then apply the same ComVisible to the 4 methods I
want to expose and set it to true.
I then go to the MSDN and find that is says "Setting the attribute to false
for a specific type hides that type and its members. However, you cannot
make members of a type visible if the type is invisible."
These seem to contradict each other in a big way. Does anyone have a
definate answer to this one?
7. Q: ComVisible and CLSCompliant
8. tlbexp in 2.0 requires ComVisible?
I am having a really weird problem in framework 2.0: when I run tlbexp on my
assembly, I am getting an empty type library unless I explicitly mark all my
classes as ComVisible. This is competely different from 1.0/1.1 behaviour;
tlbexp used to export all classes which were not explicitly marked as
ComVisible(false). I cannot find anything about it in the list of breaking
changes, and this seems to be a big incompatibility with the previous
versions, could this possibly be true? Anybody else came accross this problem?