locked
Get originating exception details from SEHException? RRS feed

  • Question

  • We have a very large application that we are moving to C# over the course of several years. There is still a lot of "legacy" C++ code that was originally making heavy use of COM; especially ADO Recordsets. We now have all of the C++ projects compiled with /clr and have some of the C++ code using .NET methods and calling our C# libraries. Due to how the original C++ code was written (i.e. every method returns a "result code"), every method has a try/catch. The original pattern used was:

    try
    {
    }
    catch (_com_error& e)
    {
    }
    catch (...)
    {
    }
    

    With that pattern, if the code attempts to access a recordset field that doesn't exist (e.g. pors->Fields->GetItem(99)->Value), the exception is thrown and caught in the "catch (_com_error& e)" block and e.Error() = -2146825023 and e.Description = "Item cannot be found in the collection corresponding to the requested name or ordinal.".

    Since we now have C++ code using .NET, I would like to change the pattern to:

    try
    {
    }
    catch (SEHException^ seh)
    {
    }
    catch (Exception^ e)
    {
    }

    With this pattern, sample scenario, the exception is caught (as I expect) in the "catch (SEHException^ e)" block but the e.HResult = -2147467259 and e.Message = "External component has thrown an exception.". The upside of catching SEHException is that I get an accurate Callstack I can log (something we didn't have before). However, as you can see, we've lost the detail of what the underlying issue was ("Item cannot be found in the collection corresponding to the requested name or ordinal.").

    Is there any way for us to obtain that original HResult and/or error description in the catch SEHException? (Note, I also tried adding a "catch (COMException^ com)" block but it never got hit.

    Thanks,

    Brad

    Friday, May 22, 2020 12:03 PM

All replies

  • Its ugly but you could nest the exception handlers -

    int main()
    {
    	try
    	{
    		try
    		{
    			_com_util::CheckError(E_INVALIDARG);
    		}
    		catch (_com_error& e)
    		{
    			cout << "Error " << hex << e.Error() << dec << " Message " << e.ErrorMessage() << endl;
    			throw;  //rethrow
    		}
    	}
    	catch (SEHException^ e)
    	{
    		Console::WriteLine("Error {0} Message {1}", e->ErrorCode, e->Message);
    	}
    
    	return 0;
    }
    

    You would get both the detail from the _com_error object and  the stack trace from SEHException.

    Friday, May 22, 2020 3:07 PM
  • The problem with that is the Callstack in the SEHException shows the line of code that did the "throw" and not the line of code that caused the error. I can't realistically put a try/catch around every line of code that may cause a COM error because there could be 100's in one method.
    Friday, May 22, 2020 6:29 PM
  • Hi Brad Salmon,

    Thanks for your feedback.

    In order to get more help about this problem, you can consider posting your question in Developer Community forum.

    Thank you for your understanding.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, May 26, 2020 6:37 AM