IErrorInfo in c# - c#

There is a C++ COM. And it sometimes throws an exeption on SomeMethod(). C++ Com supports ISupportErrorInfo and fills IErrorInfo. How can I get the IErrorInfo.Description in c#?
This code catches the error but there is no cpp message in it.
try
{
COM.SomeMethod()
}
catch (COMException exn)
{
string ACppErrorMessage = exn.message;
outputError(ACppErrorMessage);
}

According to the documentation the Description field of IErrorInfo maps to Message of the exception object if HRESULT contains that information, otherwise it just populates with the defaults.
If Message is empty then I can only assume no information is being returned from the HRESULT.

Related

C# vs PowerShell. How to get detailed exception info?

I'm using some external library though COM interface.
I have generic class for that.
Database.Connector connector = new Database.Connector();
string connectString = "srvr=nonexisthost;database=test;"; // bogus connect string
try
{
var database = connector.Connect(connectString);
}
catch (COMException ex)
{
Console.WriteLine(ex.Message);
}
Trying to build a error proof logic I intentionally provoke an exception.
And I have discovered that C# COMException contains only generic info, like:
Error HRESULT E_FAIL has been returned from a call to a COM component.
while executing samey code in PowerShell results in more detailed description:
$connector = New-Object -ComObject Database.Connector
$connectString = "srvr=nonexisthost;database=test;"
$database = $connector.Connect($connectString)
Error while executing transaction with an information base
server_addr=nonexisthost descr=11001(0x00002AF9): Host is unknown.
line=1048 file=src\DataExchangeCommon.cpp
My question is: what should I do in order to get same error info in C# (if it is possible)?
I'm not a COM Interop expert but I'll try to answer what I know and hope it will help you.
From the managed side
If the HRESULT is recognized by the runtime (CLR), the runtime automatically creates a specific managed exception for the error (e.g. FileNotFoundException). Otherwise, the runtime creates a generic COMException object which says "I don't know what this HRESULT meaning".
If the unmanaged code provides error info, you will see it in the ErrorCode property, otherwise, you will see just the HRESULT code.
You can try to search for this code (google\github) to obtain more info.
From the unmanaged side
You need to implement ISupportErrorInfo and IErrorInfo interfaces to provide more info.
So to answer your question, in C#, you can't get more info in the COMException object if this info is not provided.
For more info:
COMException, Handling COM Interop Exceptions, IErrorInfo, ISupportErrorInfo, HRESULT's mapping, Common HRESULT values

Runtime casting of COM objects in C#

I am working on a application which needs to communicate via COM interface with multiple CAD applications (not in the same time). I want to have nice and reusable code, but I came across problems with type casting of COM objects when I made generic application handle getter method.
What I tried so far:
This is the attempt I would like the most if it worked.
public static TCadAppType CadApp<TCadAppType>()
{
dynamic cadApp = default(TCadAppType);
//Here under Dynamic View/Message there is already an error
// Message = "Element not found. (Exception from HRESULT: 0x8002802B (TYPE_E_ELEMENTNOTFOUND))"
// cadVersion.Value evaluates to "SldWorks.Application"
cadApp = (TCadAppType)Marshal.GetActiveObject(cadVersion.Value);
//Following 2 lines of code are for testing purposes only, i am testing with Solidworks API
AssemblyDoc Assembly;
//The exception is thrown when I try to access some method from the Solidworks API
Assembly = (AssemblyDoc)cadApp.OpenDoc6("some parametras...");
}
Attempt using Convert class
// Another attempt using Convert class
public static TCadAppType CadApp<TCadAppType>()
{
dynamic cadApp = default(TCadAppType);
// cadVersion.Value evaluates to "SldWorks.Application"
cadApp = Marshal.GetActiveObject(cadVersion.Value);
cadApp = Convert.ChangeType(cadApp, typeof(SldWorks.SldWorks));
// Exception is thrown with the following message:
// Message = "Object must implement IConvertible."
}
I really thought that I am on the right track, since there is an article on Microsoft Docs website explaining how dynamic can help you with com interopt: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic#com-interop
Any ideas how I can do this runtime casting a keep my code as reusable as possible?
My software setup:
Win 10
Project is targeted for .NET 4.7.2
First Tests are with Solidworks 2019
Turns out that the my coding attempt 1 was valid c# code indeed.
I tried it using with Autodesk Inventor, and it works.
So the only thing left for me is to conclude that this is some bug from Solidworks and their COM interfacing.
Thank you Optional Option for your interest in the topic.

C# DllExport -Can't use AForge functions

I am trying to export code from a function in C# to Delphi. I used DllExport with stdcall convention and made some tests :it works. I tested for integers and strings as params. The problem occurs when I try to use a class from Aforge library in C#. Delphi returns an error: "External Exception E0434F4D".
public class ProcessClass
{
[DllExport(CallingConvention=CallingConvention.StdCall)]
public static void ProcessImage()
{
try
{
Erosion erosion = new Erosion();
}
catch (Exception Ex)
{
}
}
}
Delphi code:
procedure ProcessImage; stdcall; external 'C:\Users\Reznicencu Bogdan\source\repos\OCR\OCR\bin\x86\Release\OCR.dll';
procedure TForm1.FormCreate(Sender: TObject);
begin
ProcessImage;
end;
The error apears at Erosion.Actually every function I use from Aforge library generates an error. I used Try/catch because I know Delphi can't catch exceptions from unmanaged code but it still doesn't work.
How can I solve this error?
The event log says: First chance exception at $767EDDC2. Exception class EExternalException with message 'External exception E0434F4D'. Process Project1.exe (9528)
The problem appears to be related to the location of the AForge DLLs. If you place those, and your class library DLL, in the same directory as your Delphi executable then the error disappears.
Perhaps there is some other way to tell AForge where to locate its DLLs. I will leave that as an exercise for the reader to investigate.

The description string for parameter reference (%1) could not be found

I'm getting this exception when trying to read from the Windows Log using C#'s method EventRecord.FormatDescription():
System.Diagnostics.Eventing.Reader.EventLogException: The description string for parameter reference (%1) could not be found
at System.Diagnostics.Eventing.Reader.EventLogException.Throw(Int32 errorCode)
at System.Diagnostics.Eventing.Reader.NativeWrapper.EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, EvtFormatMessageFlags flag)
at System.Diagnostics.Eventing.Reader.ProviderMetadataCachedInformation.GetFormatDescription(String ProviderName, EventLogHandle eventHandle)
The exception happens when the text of the event contains the string %% followed by a long number (some events from a source I don't control contain that pattern). Those %% are intended to be just text, I don't expect any parsing intelligence from Windows at that point.
Do you know what I can do to avoid .Net from throwing this error when the text of an event contains that pattern?
Here are the PowerShell commands that will cause the exception next time you try to read the event from a C# program:
New-EventLog -LogName Application -Source MyApp
Write-EventLog -Source MyApp -LogName Application -Message "%%4294967295" -EventId 3
The workaround I ended up implementing is as follows:
private string FormatEventDescription(EventRecord eventRecord)
{
try
{
return eventRecord.FormatDescription();
}
catch (EventLogException e)
{
return eventRecord.ToXml();
}
}
This is less than satisfactory, as that XML is not user-friendly, but at least it has all the information needed in case we need to know the original content of the EventRecord. Note the XML doesn't necessarily contain the description string inside, sometimes these events have a list of parameters which are used to fill a message template to generate the description string, so in this case you'll get the raw params.

C# Problems with XML Serialization

i have a problem with a webservice but i don´t see the error. I have used a wsdl to generate the Web Reference in VS2017. This is the class which was generated:
https://gist.github.com/meteora1986/b43c9750ddeb50187420edd6741301f5
When using this class the xml used for the webservice is not generated with the XMLAttributes-options. While debugging i discoverd following errors by the XMLImporter:
errors
So i tried to serialize it to get a more detailed error message with code like
try
{
var serializer = new XmlSerializer(typeof(ari_webserviceService));
}
catch (Exception ex)
{
// codes
}
And got from from the exeption these messages:
1. inner Message: There was an error reflecting field 'Site'.
2. inner MessageThere was an error reflecting type 'System.ComponentModel.ISite'.
But these fields or types aren´t used in the webservice class? Can anybody help?
I have absolutly no idea of web-services in general.
But your webservice is derived from SoapHttpClientProtocol. If you go up the base-classes by HttpWebClientProtocol and WebClientProtocol to finally end with Component you'll see the property Component.Site.
You might be able to solve your problem if you implement the IXmlSerializable interface to have full control what (and how) you want to serialize the data...

Categories