473,240 Members | 1,704 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,240 software developers and data experts.

COMException HResults not Transferred to MFC Client

I'm trying to send custom COMExceptions from my C# server. My test client in
C# has no problem reading the HRESULT I send (say, 0x80040002). Needless to
say, the MFC client in C++ allows this HRESULT only to the .tli file, which I
assume is part of the client. The next thing that happens, it is converted to
an SEHException with a value of 0x80004005. This happens everytime, and does
it for any derivative of SEHException.

Is there some attribute of decoration I need to make?

I can post the code, it is pretty simple.
Feb 8 '06 #1
4 5294
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?

"dynastar" <u18512@uwe> wrote in message news:5b8bd64680cf0@uwe...
I'm trying to send custom COMExceptions from my C# server. My test client
in
C# has no problem reading the HRESULT I send (say, 0x80040002). Needless
to
say, the MFC client in C++ allows this HRESULT only to the .tli file,
which I
assume is part of the client. The next thing that happens, it is converted
to
an SEHException with a value of 0x80004005. This happens everytime, and
does
it for any derivative of SEHException.

Is there some attribute of decoration I need to make?

I can post the code, it is pretty simple.

Feb 8 '06 #2
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
Dmytro Lapshyn [MVP] wrote:
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.


--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/For...sharp/200602/1
Feb 8 '06 #3
Hi,

Please try using Marshal.ThrowExceptionForHR and correct HR codes first. If
this does not help, please follow up in this thread.

I am also curious why do you inherit your server class from
MarshalByRefObject. Is your server an out-of-proc (DCOM) server?

"dynastar via DotNetMonster.com" <u18512@uwe> wrote in message
news:5b9337f2bea1d@uwe...
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
Dmytro Lapshyn [MVP] wrote:
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.


--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/For...sharp/200602/1

Feb 9 '06 #4
Hi Dmytro,
This is a remoted server which is why I use the MarshalByRefObject. I have
been working with C# servers for over a year now, and ran in to this problem
early on. Normally, COM objects return HRESULTs that can simply be assigned
as the STDMETHODIMP return value to the call. I simply want to maintain this
functionality because I have to deal with legacy code.

I have now tried your suggestion but get the same result: the 0x80040001
HRESULT becomes 0x80004005 and I must use try..catch blocks. There is
something in the layer between the c# agent and the MFC proxy that is
modifying the HRESULT to the base class (SEHException) HRESULT.

Thanks,
Steve

Dmytro Lapshyn [MVP] wrote:
Hi,

Please try using Marshal.ThrowExceptionForHR and correct HR codes first. If
this does not help, please follow up in this thread.

I am also curious why do you inherit your server class from
MarshalByRefObject. Is your server an out-of-proc (DCOM) server?
Hi Dmytro,
This is the entire server class (ServerTest assembly):

[quoted text clipped - 216 lines]

I can post the code, it is pretty simple.


--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/For...sharp/200602/1
Feb 9 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: MikeH | last post by:
I have the weirdest problem with an Access 97 database... The application comprises the usual front-back split database. It's built around Access 97 and had been running without serious problems...
0
by: lakshmi | last post by:
Hi all I posted a related question a couple days back. I did get a few helpful replies. However, I've not yet figured out the solution. I've read that passing HRESULTs back from .NET to COM is...
3
by: Shmulik | last post by:
I have an application written in C# that creates a queue of items to process, connects via a TCP connection to a server on a Unix box, and then passes data files to the Unix box for processing...
2
by: Jim Lacenski | last post by:
I have a VB class that uses .NET and ADODB to write into an Excel spreadsheet (via Jet) on a server as part of a web application. ADODB is used instead of ADO.NET because it greatly simplifies the...
2
by: Sabi | last post by:
hi, I have created a collection of serviced components that performs money transaction between 5 schools. I have marked all the components with Transaction(TransactionOption.Required) attribute. All...
3
by: Jay A. Moritz | last post by:
I have an application that loads IE and iterates through web pages to retrieve information from the page then activates specific controls to retrieve the next page and iterate through that page for...
0
by: =?Utf-8?B?QnVyZ2F6b24=?= | last post by:
Hi, I have a COM-.NET exception handling problem and I would appreciate your help. I have a COM server that “throws exception” from time to time (the COM object implements...
1
by: TheFid | last post by:
In case someone knows off the top.... I am accessing a COM-interface-exposing C# dll in VC++ 6. The C# disp method can throw a COMException. Do I catch a _com_error ? It's not obvious from the...
19
by: Kapps | last post by:
Hi, I'm having a problem with my program not being able to run on certain computers. They have the basics, such as the .Net Frameworks. Upon trying to run the program, it gives the error: ...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.