I have a WPF Application, and I must load the DLL cc3260mt.dll
I call it by using LoadLibrary(), but for whatever reason I am getting an ArithmeticException.
Here is what my code looks like :
public partial class MainWindow : Window
{
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
static extern IntPtr FreeLibrary(IntPtr hModule);
public MainWindow()
{
InitializeComponent();
try
{
string cc3260mtPath = "dll/cc3260mt.dll";
IntPtr cc3260Link = LoadLibrary(cc3260mtPath);
}
catch (Exception ex)
{
Console.WriteLine("ERROR : " + ex.Message);
}
} // <-- This is where I get the Exception.
}
When I run my code step by step, I can clearly see that the exception appears when I get out of my MainWindow() class.
Do you guys have any idea what gets me this exception ?
That is the C runtime support library for old Borland C or C++ programs. And yes, it does something that's very incompatible with .NET code in general, and WPF in particular, it reprograms the floating point unit control register. It enables hardware exceptions, triggered when a floating point operation fails. Particularly problematic in WPF because is likes to use Double.NaN a lot. Which generates an FPU exception, the CLR intercepts it and re-raises it as an ArithmeticException.
You will have to undo what this DLL did and restore the FPU control word. This is problematic, .NET doesn't give you direct access to the hardware like that. There is however a trick you can use, the CLR automatically reprograms the FPU when it handles an exception. So you can intentionally generate an exception and catch it. Like this:
IntPtr cc3260Link = LoadLibrary(cc3260mtPath);
try { throw new Exception("Ignore this please, resetting the FPU"); }
catch (Exception ex) {}
Do note the consequence of this, you'll now have the native code running without the exceptions it normally relies on. Maybe that will work.
Related
I'm creating a C++ DLL to be used in C#. This DLL throws exceptions whenever anything is wrong and the idea is to handle these in the C# code.
I created a new exception class in C++ inheriting from std::runtime_error because I not only need the what but also a numeric ID:
class insight_exception: public std::runtime_error
{
public:
explicit insight_exception(const int id, const std::string message):
std::runtime_error(message), id{id}
{}
virtual ~insight_exception() noexcept {}
const int id;
};
Whenever something goes wrong in the C++ code I do this:
throw insight_exception(103, "size Pointer is NULL");
I have a little example in C# to "exercise" the DLL, just to test it before sending it to our C# developer, and when I execute the little C# program I can verify that the DLL is throwing the exceptions because I'm getting this:
terminate called after throwing an instance of 'insight_exception'
My problem is that I don't know any C# and I don't really know to "import" the insight_exception class into C# so I can catch it.
Solutions like this post don't help because they assume you can use the class by using a function like this:
insight_exception* create_insight_exception()
{
return new insight_exception();
}
And I can't do that because I need something like this in C#
try
{
}
catch (insight_exception e)
{
}
So I can't create the class like:
IntPtr insight_exception = create_insight_exception();
One important thing to know is that I'm creating the DLL on Linux by cross-compiling using MinGW, so I can't do #include <Windows.h> or any other windows-related includes or imports when creating the DLL. I don't really use Windows but only for my little test C# code.
EDIT:
Thanks to a comment, I looked into the following questions:
C# not catching unhandled exceptions from unmanaged C++ dll
This one looks promising but the problem is that the answer suggest a compilation done in Windows. I tried to add the /EHa compilation flag equivalent in GCC (-funwind-tables) but that doesn't help. I still can't catch the exception using catch (SEHException ex) nor catch (Exception ex) in the C# code.
Can you catch a native exception in C# code?
Suggests using Win32Exception but that doesn't work either. I can't catch the exception with catch (Win32Exception ex) in the C# code.
My WPF app uses external DLL's method (c++, nothing with UI, just logic) like this:
[DllImport("myExternDll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern int externalMethod(string str);
int SomeWPFMethod()
{
int res;
try
{
res = externalMethod(str);
}
catch(Exception e)
{
LogError(e)
return -1;
}
return res;
}
Note, that SomeWPFMethod called in separate from UI thread (if this matter).
When there is something wrong inside dll I've got
An unhandled exception of type 'System.AccessViolationException'
occurred
exception.
A have unhanded exception method set for app, but this does nothing:
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
e.Handled = false;
return;
}
ShowUnhandledException(e);
}
Is there possible somehow to handle the exception to prevent application from crash?
If extern method fails, I don't want to do anything, but app should still work. Now it's crashed.
Since SomeWPFMethod is called in a thread separate from the UI thread,
Application.Current.DispatcherUnhandledException
will not be able to catch this exception since it catches unhandled exceptions only from the main UI thread created by WPF.
Seems you need to use
AppDomain.CurrentDomain.UnhandledException
It catches unhandled exceptions generated from all threads running under the context of a specific application domain.
You can refer to the following articles that cover proper way to handle unhandled exceptions in WPF at great depth -
https://dzone.com/articles/order-chaos-handling-unhandled
https://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Hope this solves your problem.
I have a simple function inside of a click handler that has a try catch block. If I throw an exception within this try catch block it catches the exception successfully.
If I put a call to an unmanaged DLL before I throw the exception the exception is unhandled and not caught.
What is the unamanged DLL call doing that could be breaking my programs exception handling?
If I run the program in debug mode it catches the exception even with "break on exception" unticked for all exceptions. The application does not crash and runs as expected.
If I run the program as "start without debugging" and hit debug when it crashes I get the following error "Stack cookie instrumentation code detected a stack-based buffer overrun"
edit:
It appears the stack overflow breaks the exception handling
I've attached a simplified program that produces the crash.
ISOConnection _comm; //This is instantiated at another time in the same thread
//C# test function that crashes when run without a debugger attached
bool DoMagic()
{
try
{
//if I uncomment this line the exception becomes unhandled and cannot be caught
//_comm.ConnectISO15765();
throw new Exception();
}
catch (Exception ex)
{
MessageBox.Show("Caught exception")
}
//Within ISOConnection class
public void ConnectISO15765(){
...
lock(syncLock){
uint returnCode = J2534Interface.PassThruConnect((uint)DeviceId, (uint)ProtocolID.ISO15765, (uint)ConnectFlag.NONE, (uint)BaudRate.ISO15765, ref ChannelId);
//C# UnmanagedFunctionPointer allocation code
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint PassThruConnect(uint deviceId, uint protocolId, uint flags, uint baudRate, ref uint channelId);
public PassThruConnect Connect;
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
m_pDll = NativeMethods.LoadLibrary(path);
...
pAddressOfFunctionToCall = NativeMethods.GetProcAddress(m_pDll, "PassThruConnect");
if (pAddressOfFunctionToCall != IntPtr.Zero)
Connect = (PassThruConnect)Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall,
typeof(PassThruConnect));
//C++ function declaration
long PassThruConnect(unsigned long DeviceID, unsigned long ProtocolID, unsigned long Flags, unsigned long Baudrate, unsigned long *pChannelID);
UPDATE
If I replace the call to the UnmanagedFunctionPointer PassThurConnect with the following the crash does NOT occur
[DllImport("op20pt32.dll", EntryPoint = "PassThruConnect", CallingConvention = CallingConvention.Cdecl)]
public static extern uint PassThruConnect2(uint deviceId, uint protocolId, uint flags, uint baudRate, ref uint channelId);
Is there something I am not performing or I am performing incorrectly when assigning the UnmanagedFunctionPointer that would cause the lack of a debugger to create a stackoverflow crash?
What is even stranger is this code appeared to work a few weeks ago. The main changes is the try catch was in another thread and I wasn't using lock(syncLock). Everything is now in one thread however the same crash occurred when run in a BackgroundWorker as well.
UPDATE #2 PROBLEM SEMI-SOLVED
Ok so I rolled back through my commits one by one until it worked. What changed is I went from .NET 3.5 to .NET 4.0
.NET 3.5 does not crash regardless of attaching a debugger or not. .NET 4.0 crashes if a debugger is not attached. To rule out a bug in my code I simply deleted the ConcurrentQueue for my log (the only 4.0 feature I was using) and converted my current code base back to 3.5 and I do not get this error.
To be 100% sure it is an issue with 4.0 I then converted my code base back to 4.0 from 3.5 and left the ConcurrentQueue out (literally just changed the build options and did a rebuild) and the StackOverflow crash is back.
I would prefer to use 4.0, any ideas how to debug this issue?
edit: .NET 4.6.1 also crashes
UPDATE #3
http://codenition.blogspot.com.au/2010/05/pinvokestackimbalance-in-net-40i-beg.html
Apparently pinvokestackimbalance is basically ignored in .NET 3.5, so the problem still exists, it just doesn't crash my application.
Adding the following code to App.Config causes .NET to repair the stack when transitioning back to managed code. A small performance hit but it will fix the problem.
Whilst this does fix the problem, I'd like to know what is wrong with my UnmanagedFunctionPointer to cause the problem in the first place.
<configuration>
<runtime>
<NetFx40_PInvokeStackResilience enabled="1"/>
Edit: this thread isn't a duplicate, the other one is deleted...
Ok so the problem is the calling convention should be StdCall not Cdecl
This makes sense as the generic J2534 API documentation specifies the following header. Although the header file I was supplied does not make this specification.
extern "C" long WINAPI PassThruConnect
(
unsigned long ProtocolID;
unsigned long Flags
unsigned long *pChannelID
)
Where WINAPI is also known as StdCall not Cdecl like most C/C++ libraries would typically use.
.NET 3.5 allows the wrong calling convention and will "fix" the stack. As of 4.0 this is no longer the case and a PinvokeStackImbalance exception is raised.
You can force 4.0 to also fix the stack with the following code added to your App.Config
<configuration>
<runtime>
<NetFx40_PInvokeStackResilience enabled="1"/>
Or you can simply fix your calling convention by changing Cdecl to StdCall:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate uint PassThruConnect(uint deviceId, uint protocolId, uint flags, uint baudRate, ref uint channelID);
This a question arising from this thread: Native C++ use C# dll via proxy C++ managed dll
In a nutshell, I'm loading (my) C# extension into a native process via a DLL. The extension needs to show a form so that the user can control it. I'm using standard .NET forms, no 3rd party librarys or anything, and my form is not showing up. Worse yet, it hangs the target process. It's not using any CPU, so I get the feeling its waiting for some function to return, but never does.
Also of interest is that the "Initialize method" message box pops up, but not the "Test" message box. I've tested everything I can think of (STAthread, threads, DisableThreadLibraryCalls, plus different code locations), every way to Sunday. I'm inclined to think it's some obscure detail of Win32 interop, but I can't find anything that would seem to cause these symptoms.
Can one of you experts take a look at my code and point out what the issue is?
/// <summary>
/// Provides entry points for native code
/// </summary>
internal static class UnmanagedExports
{
[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.StdCall)]
public delegate int SendRecv([MarshalAs(UnmanagedType.SafeArray)]byte[] ByteArray, UInt64 Len);
[STAThread]
[DllExport("Initialize", CallingConvention.StdCall)]
public static int Initialize(IntPtr hInstance, SendRecv Send, SendRecv Recv)
{
return DLLinterface.Initialize(hInstance, Send, Recv);
}
[DllExport("Terminate", CallingConvention.StdCall)]
public static void Terminate()
{
DLLinterface.Terminate();
}
}
internal class DLLinterface
{
static System.Threading.Thread uiThread;
[STAThread]
internal static int Initialize(IntPtr hInstance, UnmanagedExports.SendRecv Send, UnmanagedExports.SendRecv Recv)
{
MessageBox.Show("Initialize method");
try
{
uiThread = new System.Threading.Thread(Run);
uiThread.Start();
}
catch (Exception ex)
{
MessageBox.Show("Failed to load: " + ex.Message, "Infralissa error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return 1;
}
[STAThread]
private static void Run()
{
MessageBox.Show("Test");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
internal static void Terminate()
{
MessageBox.Show("Terminating.");
if (uiThread.IsAlive)
uiThread.Abort();
}
}
It seems that the target itself was at fault. It wasn't loading the extensions directly, but instead loading a native "exensionManager.dll", where, as luck would have it, they were using DllMain to load up MY extension. In other words, I was trying to load a form under loaderlock and ran into a deadlock as. NET tried to load other assemblies.
The answer was simple, I had to show the form on a new thread. However, .NET's threading was also hanging, as it, too, required a library load which deadlocked.
In the end, I had to resort to a vanilla P/Invoke to CreateThread() directly, but the form is finally showing up.
I'm writing a C# .NET 3.5 program wich uses the latest MediaInfoLib Dll.
It seems that it causes an exception for some files.
I want to catch those exceptions and ensure my program continues running,
but for some reason I can't catch it with a simple try/catch statement.
PInvoke Methods:
[DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_New();
[DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_Open(IntPtr Handle,MarshalAs(UnmanagedType.LPWStr)] string FileName);
Usage:
Handle = MediaInfo_New();
try{
MediaInfo_Open(Handle, FileName)
} catch { }
Calling MediaInfo_Open(Handle, FileName) might cause an exception.
Instead of catching the error with the try/catch statement, my program exits and "vshost32-clr2.exe" crashes. (It also crashes as a release build and with no debugger attached)
After searching the web, I found someone who suggested to check "Enable unmanaged code debugging", which only resulted in my program exiting without vshost32-clr2.exe crashing.
Any idea how I can catch the exception?
If the unmanaged DLL is causing the crash (rather than just returning an error code of some kind), then there's no way to catch it. Once you've gone outside of the .NET runtime's control, it's entirely up to the unmanaged code; there's nothing the .NET runtime can do.
I've had a similar problem (with BSTR specifically) but hopefully this will help.
There is a bug in .NET (fixed in 4.0) when internally marshalling strings back from unmanaged code. More Info
The work-around is to change your P/Invoke signature to use an IntPtr and do the string marshalling yourself.
[DllImport("MediaInfo.dll", EntryPoint = "MediaInfo_Open")]
private static extern IntPtr _MediaInfo_Open(IntPtr handle, IntPtr filename);
internal static extern IntPtr MediaInfo_Open(IntPtr handle, string filename)
{
IntPtr stringPtr = Marshal.StringToBSTR(filename);
return _MediaInfo_Open(handle, stringPtr);
}