Hi Dmytro,
This is the entire server class (ServerTest assembly):
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime; // to set the lease to infinite
using System.Runtime.InteropServices;
namespace ServerTest
{
/// <summary>
/// Summary description for IOComponent.
/// </summary>
public class Class1 : MarshalByRefObject, ServerData
{
static int m_EC;
#region Marshal By Reference Methods
public override Object InitializeLifetimeService()
{
return null;
}
#endregion
public Class1()
{
m_EC = 0;
}
public int MAKE_HRESULT(int sev, int fac, int code)
{
return (((sev)<<31) | ((fac)<<16) | ((code)));
}
#region ServerData Members
public void ThrowException()
{
int hRes = MAKE_HRESULT(1,4,(int)m_EC++);
throw new COMException("My new exception",hRes);
// Creates
an
HRESULT of 0x80040000
}
#endregion
}
}
The ServerData interface is this:
using System;
namespace ServerTest
{
/// <summary>
/// Summary description for serverInterface.
/// </summary>
public interface ServerData
{
// methods
void ThrowException();
}
}
To use this, the #import of the server code creates a secondary header
file (.
tli) from the .tlb.
Here's my code for the client proxy, also written in C#:
// ServerProxy.cs
using System;
using ServerTest;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime; // to set the lease to infinite
using System.Runtime.InteropServices;
namespace COMServerPS
{
/// <summary>
/// Summary description for ServerProxy.
/// </summary>
public class ServerProxy : MarshalByRefObject, ServerData
{
public Class1 _Server; // object
#region Marshal By Reference Methods
public override Object InitializeLifetimeService()
{
return null;
}
#endregion
public ServerProxy()
{
_Server = new Class1();
}
#region ServerData Members
[PreserveSig]
public void ThrowException()
{
try
{
_Server.ThrowException();
}
catch (Exception ex)
{
int hr = Marshal.GetHRForException(ex);
throw ex;
}
}
#endregion
}
}
This is the MFC header file:
// WindowsMFCApplicationDlg.h : header file
//
#pragma once
#import "COMServerProxy.tlb" named_guids
#import "ServerTest.tlb" named_guids
// CWindowsMFCApplicationDlg dialog
class CWindowsMFCApplicationDlg : public CDialog
{
// Construction
public:
CWindowsMFCApplicationDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
...
// Namespace(from .tlb)::InterfacePtr
ServerTest::ServerDataPtr m_ioServer;
// Implementation
protected:
...
public:
afx_msg void OnBnClickedButton1();
};
And the implementation file:
// WindowsMFCApplicationDlg.cpp : implementation file
//
#include "stdafx.h"
#include "WindowsMFCApplication.h"
#include "WindowsMFCApplicationDlg.h"
#include ".\windowsmfcapplicationdlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace System;
using namespace System::Runtime::InteropServices;
...
BOOL CWindowsMFCApplicationDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
// must call CoInitialize() at least once prior to calling
CreateInstance()
HRESULT hRes = CoInitialize(NULL);
// CreateInstance(Assembly Name::Class Name)
hRes = m_ioServer.CreateInstance(__uuidof(COMServerProxy::ServerProxy));
return TRUE; // return TRUE unless you set the focus to a control
}
void CWindowsMFCApplicationDlg::OnBnClickedButton1()
{
HRESULT hr = S_OK;
try
{
hr = m_ioServer->ThrowException();
}
catch(COMException* ex )
{
int ec = ex->get_ErrorCode();
Exception *exc = ex->GetBaseException();
hr = Marshal::GetHRForException(ex);
}
catch(Exception* ex )
{
hr = Marshal::GetHRForException(ex);
// HRESULT is 0x80004005
}
}
Tha's about it. It works between the managed types, but not unmanged C++.
Thanks,
Steve
Hi,
First of all, how to you throw custom COMExceptions? I'd recommend that
you
did it with Marshal.ThrowExceptionFromHR.
Also, the exception code itself looks suspicious as it can easily interfer
with system error codes. As far as I remember, it is safe to use codes
from
0x80040201 and above for custom errors (VB6 has a dedicated constant for
that called vbObjectError).
Finally, as I am not an MFC programmer, can you please elaborate on what
the
.tli file is?
I'm trying to send custom COMExceptions from my C# server. My test
client
in
[quoted text clipped - 11 lines]
I can post the code, it is pretty simple.