P/Inoke catching native exception - pinvoke

I am testing a C# .NET 4.0 application which interacts with an C++ unmanaged DLL through PInvoke and I'd like to catch any exceptions thrown by the dll.
I have the dll function wrapped in try/catch clause to handle the native exception, but when it gets fired it is ignored. Tried :
try { } catch {}
try {} catch (Exception)
try {} catch (SEHException)
try {} catch (Win32Exception)
to no avail
The only option that works is by setting the DllImport SetLastError property to true and
after calling the function checking with :
if (Marshal.GetLastWin32Error() !=0)
It is a satisfactory solution but I just wonder why the other options do not have any effect as well as wonder if if the native exception is fired by the unmanaged dll or by the Windows API itself since for example the exception is a :
System.ComponentModel.Win32Exception (0x80004005): There is not enough space on the disk
is that a notification from the Windows API itself ?

The simple explanation is that the native code just doesn't throw an exception. And yes, using GetLastWin32Error() is boiler plate for any Windows api function. Other code might use it too, although it isn't terribly common, anybody can call SetLastError() to set the thread's error code. C code otherwise never intentionally throws exceptions, the language doesn't support it.
The 0x80004005 error code is COM error code, E_FAIL. You don't use pinvoke to call COM functions, the CLR's support for COM interop takes care of it through an import library. You do get exceptions for COM errors, the CLR throws them when it sees that the COM method returned a failure code. It also uses IErrorInfo to get a better description for the error code, returned in the Exception.Message property.

Related

On passing exceptions from C++ to C#

In a webpage it's suggested that:
The moral of this story: don’t let exceptions propagate between managed and unmanaged code. The results won’t be pretty.
also suggested:
This is particularly pertinent when wrapping C++ methods. C++ exceptions will need to be mapped into an “out” parameter or a return value, so that managed code can know what error occurred, and (optionally) throw a managed exception to “propagate” the original C++ exception.
Based on the above statements, my understanding is that the safest (best?) way to pass exceptions from C++ to C# is by return value or output parameter. Is my understanding correct?

Calling c# code from managed c++ crashes

I have an unmanaged c++ DLL that calls c# code through a managed c++ wrapper. The unmanaged c++ DLL is a plug-in for some application (outside my control). When this application calls the unmanaged c++ DLL everything works fine until the managed c++ code tries to use the c# code. Then it crashes.
I have written a test application that does the same thing as the application, that is, it calls the unmanaged c++ DLL. This works fine.
The code is as simple as it could be:
unmanaged c++:
extern "C" __declspec(dllexport) void UnmanagedMethodCalledUponByApplication()
{
new Bridge();
}
managed c++:
Bridge::Brigde()
{
gcnew Managed(); // This line crashes
}
c#:
public class Managed
{
}
I have tried to add a try-catch (...) block around the problematic line but it doesn't catch the error.
If I replace the gcnew Managed(); line with MessageBox::Show("Alive!"); it works fine. So my guess is that something is wrong with my c# project settings.
I have tried to compile it with different platforms (Any CPU and x86). I have tried to change target framework. I have tried to call a static method in Managed instead of using gcnew. Still crashing.
Any ideas what might be the problem?
Update:
After advise in comments and answer, I attached the debugger. Now I see that I get a System.IO.FileNotFoundException saying that the managed DLL (or one of its dependencies) can't be found.
Here's a guess: The DLLs are placed together, but they are not located in the current directory. The unmanaged c++ DLL is loaded correctly since the main application specifies the path to it. The managed c++ is actually a lib, so that code works fine as well. But when the managed c++ tries to load the c# DLL it looks for it in the wrong directory.
Update:
The way to fix this is to load the c# DLL dynamically, using reflection.
extern "C" __declspec(dllexport)
Yes, that's a cheap and easy way to get the compiler to generate the required stub that loads and initializes the CLR so it can execute managed code. Problem is, it doesn't do anything reasonable to deal with exceptions thrown by managed code. And managed code likes throwing exceptions, they are a terrific trouble-shooting tool. That stops being terrific when there's no way for you to retrieve the exception information.
The best you could possibly do from native code is use the __try/__except keywords to catch the managed exception. Exception code is 0xe0434f4d. But that still doesn't give you access to the information you need, the exception message and the holy stack trace.
You can debug it. Project + Properties, Debugging, change the Debugger Type to "Mixed". Then Debug + Exceptions, tick the Thrown checkbox for CLR Exceptions. The debugger stops when the exception is thrown so you can see what's wrong.
Getting decent diagnostics after you shipped your code requires a better interop mechanism. Like using COM interop or hosting the CLR yourself.

VB.NET Throws Exception

In Java you can mark a method as might throw an exception
e.g. 'public void foo() throws exception {'
This is useful as the developer can then see to putting that method in a try catch block.
Is there a way to do this in VB.NET so that Visual Studio (as in Eclipse) warns the developer to put this code in a try catch block?
There is no equivalent.
Its pretty stupid actually, because exceptions should be exceptionnal.
Just add it in the XML documentation.
Dont forget that the throws in Java forces the calling method to surround the call by a try catch bloc ...

How are try/catch blocks implemented?

If an exception occurs in a try block, how is execution transferred to the catch block? This is not a C#/Java/C++ question, I'm just wondering how it works internally.
this is not a c#/java/c++ question. How it works internally,how the line knows to go catch statement.
How this works internally makes this pretty much a c#/java/C++ question (because it will be implemented differently).
In Java, a try block installs itself into a special table (in the class file). When the JVM throws an exception, it looks at that table to see where the next catch or finally block to go to is.
When an exception occurs a special instruction is executed (usually called interrupt). This leads to executing a generic error handler that deduces which is the latest installed suitable exception handler. That handler is then executed.
There is a difference how exceptions are technically handled between natively compiled languages such as C++ and languages using byte-code being executed on a virtual machine such as Java or C#.
C++ compilers usually generate code that protocols the information needed for exception handling at runtime. A dedicated data structure is used to remember entrance/exit of try blocks and the associated exception handler. When an exception occurs, an interrupt is generated and control is passed to the OS which in turn inspects the call stack and determines which exception handler to call.
Further details are pretty well explained in the following article by Vishal Kochhar:
How a C++ compiler implements exception handling
In Java or .NET there is no need for the overhead of maintaining exception handling information as the runtime will be able to introspect the byte code to find the relevant exception handler. As a consequence, only exceptions that are actually thrown are causing an overhead.
It is basically parsing fundamentals of the language.
You can get all info at Here
it should work in all langues somewhat like this:
if (error_occured xy while doing things in try){
call_catch_part(error xy)
}
you could do the same in C even though there is no exception handling per se.
There you would use setjmp/longjmp unfortunately you then do not get the stack unwinding and have to handle all the nitty-gritty yourself.

How do i check for mono on runtime

By default mono doesnt trust any SSL connections. So if running on mono i'd like to give a message rather then throwing an exception.
How do i check if i am running under mono at runtime? (since at compile time the CLI wont know)
I'll quote from the Mono site:
Having code that depends on the underlying runtime is considered to be bad coding style, but sometimes such code is necessary to work around runtime bugs
using System;
class Program {
static void Main ()
{
Type t = Type.GetType ("Mono.Runtime");
if (t != null)
Console.WriteLine ("You are running with the Mono VM");
else
Console.WriteLine ("You are running something else");
}
}
Couldn't you just catch the System.Net.WebException and pass your message up? This is approach #1 from the Mono site here: Using Trusted Roots Respectfully. There are a number of more (and a couple less) involved responses there if you'd like to do more, but catching the exception avoids the coding-to-runtime problem tobsen refers to.