What a nightmare COM interop is proving to me. I have a simple managed DLL containing a WPF window. I have a simple ViewController class that will eventually be launching this window but for now has an empty method that does nothing.
I have created a managed wrapper for this managed DLL, that exposes an interface registered for COM interop. I can call into my managed wrapper OK. I can display a MessageBox in the entry point of my managed wrapper DLL. However, if I attempt to call ANY method on this ViewController class in the DLL I am wrapping, I get this:
First-chance exception at 0x7c812aeb (kernel32.dll) in MfcVSApp1.exe: Microsoft C++ exception: EEMessageException at memory location 0x0012cb30..
It all worked yesterday apparently. Now some code:
My wrapper entities:
[Guid("83C799E0-9808-40c2-A1AB-80BCB77A3B18")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface IMaryln
{
void GetEphemeris(DateTime date, double latitude, double longitude);
/// <summary>
///
/// </summary>
/// <param name="date"></param>
/// <param name="latitude"></param>
/// <param name="longitude"></param>
void GetEphemeris1(Int64 millSecsSince1970, double latitude, double longitude);
}
[Guid("144DB386-D8EF-41a8-B9B1-57EE8A64600C")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ManagedProxy.Maryln")]
[ComVisible(true)]
public class Maryln : IMaryln
{
#region IMaryln Members
public Maryln()
{
System.Diagnostics.Debugger.Launch();
}
public void GetEphemeris(DateTime date, double latitude, double longitude)
{
//new EphemerisViewController().GetEphemeris(date, latitude, longitude);
}
public void GetEphemeris1(Int64 nanoSecsSince1970, double latitude, double longitude)
{
// This method does not throw. However, it will not be executed
// if any method in EphemerisViewController is called.
MessageBox.Show("Called from c++" + nanoSecsSince1970.ToString());
try
{
//new Maryln().Test(); // this will not throw
new EphemerisViewController().GetString(); // this will
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void Test()
{
MessageBox.Show("maryln test");
}
#endregion
}
The Managed DLL, referenced by the managed wrapper DLL, contains a UserControl and this ViewController:
public class EphemerisViewController
{
public EphemerisViewController()
{
}
public void GetString()
{
MessageBox.Show("me");
}
}
This DLL was also registered for COM interop but then开发者_运维百科 I unchecked that option as it did not help matters. Gurus on board, I need help here. This has consumed two working days already and I have taken 3 steps back from where I started. It all worked yesterday.
Addition
The native client is consuming my wrapper as follows:
void CMfcVSApp1Doc::LaunchEphemrisDialog()
{
HRESULT hr;
CoInitialize(NULL);
try
{
ManagedProxy::IMarylnPtr maryln(__uuidof(ManagedProxy::Maryln));
LONG64 time = 1309897499216000000;
hr = maryln->GetEphemeris1(time, 0, 0);
}
catch(...)
{
}
}
Also, I have cleaned and rebuilt solution numerous times but no luck.
Do not know what may have happened here but I decided to ditch this wrapper DLL and create a new one from scratch. I did not change the C# project I was wrapping just to see which of these two projects was causing the problem. This act alone somehow allowed me to debug each of the APIs exposed in the C# project being wrapped. Using the project debug technique suggested by Hans P, I was able to further debug my wrapper DLL. I gave a big sigh of relieve just being able to see a managed exception. Definitely a step forward.
It turned out that each call to a wrapped API in EphemerisViewController was throwing a manage exception that a dependency could not be found (located assembly manifest does not match loaded assembly....blah..blah.). We all know what causes this.
After cleaning assembly references thereby eliminating the aforementioned error, I could then call my managed DLL again. A day wasted on one hand. A lot learnt on the other hand. Why the original wrapper stopped working is beyond my comprehension but I am glad to let that go. it have have been a combination of namespace corruption and DLL loading issues but who knows.
I was getting ready to ditch COM interop and dive into MFC but boy, i am glad I stuck to my guns. Compared to C#, C++ development sucks as far as i am concerned. For example just being able to catch a general Exception in C# as apposed to the catch(...) equivalent we have for C++ is a serious benefit. All the crazy c++ syntax and head scratching routines to perform simple conversions make my head spin. Not to mention Intellisense, oh intellisense. With a expired Virtual Assist license that reminds me everyday it is laying dormant, and a tight corporate budget, I will stick to C# for a while maybe with thoughts on investigating C++ libraries like Boost when all of this is done, just in case. But boy, I am happy to get back into .NET.
Lesson learnt here for me is: with COM interop, you have to pay close attention to the details!
精彩评论