I am writing a .netCF application that interfaces to a barcode scanner on different hardware platforms. I. E. Motorola or Intermec Etc. I have wrapped their DLLs with one of my own to present a common interface and I am loading my dll at runtime with Reflection LoadFrom() and then get a Method reference.
I am able pass most parameters to the methods in my dll with one exception. I need to pass a call back function to the dll so that when a read occurs it will call back into the main program to process the barcode read.
When I invoke the method it throws an ArgumentException.
My question is how do I pass this method reference to my dll or is there a better way to do this?
public delegate void ReadNotify(BCReadData readData);
public void AttachReadNotify(ReadNotify ReadNotifyHandler)
{
if (type == ReaderType.UNKNOWN || scanIntf == null)
return;
try
{
setReadNotify.Invoke(scanIntf,new Object [] {ReadNotifyHandler});
}
catch (Exception e)
{
throw new Exception("Unable to set notify handler" + e.Message);
}
}
If your native callback uses the __stdcall calling convention, you can accomplish this using the Marshal.GetFunctionPointerForDelegate method.
Related
Currently I'm using a third party DLL for a printer. It's a C# wrapper for a C++ DLL, so it can be used in a C# application. The method for printing contains a callback function that should be called when printing is done. However, I can't get it to work, so I'm wondering if I'm implementing it correctly.
The (shortened) method of this print and callback function is:
public class PrinterWrapper
{
public uint Print(CallbackFunction callbackFunction);
public delegate void CallbackFunction();
}
In another class I'm using the print function and try to test the callback this way:
class Foo {
private void callback() {
{
Console.WriteLine("Test");
}
public void Print() {
{
PrinterWrapper wrapper = new PrinterWrapper();
wrapper.Print(this.callback);
wrapper.Print(new PrinterWrapper.CallbackFunction(this.callback));
}
}
I've tried both version of calling the Print method (both should be the same), but I'm not getting a callback. Instead, I get an APPCRASH just when the print is ready. Did some searching, found out I could catch the exception with the setting
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
It tells me it's a read/write memory protection exception. The event log also shows an error, right before my application crashes:
Application: Application.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
So it looks like the third party DLL is trying to access memory it doesn't have access to. The documentation says that the callback argument is a pointer (that's for the original C++ DLL). There is no documentation for the C# wrapper DLL.
With this info, did I correctly make use of the callback function or do I have to change something to get it working?
Had a wrong implementation of the callback delegate. Fixed it and it now works.
SEE EDITS AT THE END.
I have an app that requires to user to install a 3rd party application for mine to run. I'd like to make my application provide a warning to the user if they have forgotten to install this 3rd party app instead of just quitting as a result of trying to access a missing assembly.
In C#, I'd like to check if an assembly is included.
I thought I could use:
object.ReferenceEquals(Oject, null)
But but object.ReferenceEquals does not like to take Type as an input.
I tried:
var type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type2 in assembly.GetTypes()
where type2.Name == "Oject"
select type2);
if (type == null) {...}
But Visual Studio shows me that type can never be null.
So: Is there a simple way I can detect if I forgot to include an assembly before I access it (and the app just quits with no warning or message telling the user WHY it quit)?
I thought I could use
try
{
types = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
types = ex.Types.Where(p => p != null).ToArray();
}
from: Missing types using reflection on DLL but I'm doing this check from Program.cs that is a static class.
EDIT:
It turns out that I have the referenced assemblies but that these assemblies may not have the correct logic installed. So the references came along with all the binaries but since the 3rd party app was not installed, those binaries went bonkers when they could not reach their intended targets and it is those binaries that seem to be failings.
So... I still have this issue but it may explain I cannot "Catch" ??
An interesting fact about type loading in .NET. A type is loaded upon entering a method that uses it. An assembly is loaded when the first type is loaded. So, example code below (assuming "SomeType" is a type in the assembly you are looking for)
So by this logic you can have:
static void Main() {
if (CanLoad()) {
DoStuff();
} else {
Console.WriteLine("Some error message");
}
}
static void DoStuff() {
// Ok to reference SomeType here
}
private static bool CanLoad() {
try {
TryLoad();
return true;
} catch {
return false;
}
}
private static void TryLoad() {
Type t = typeof(SomeType);
}
With this code, what happens is this. Main calls CanLoad normally. CanLoad doesn't need any fancy type, so it happily starts up, and then attempts to call TryLoad. TryLoad, however, has a reference to "SomeType", so when the compiler attempts to enter that method, before executing any part of it, it attempts to load the assembly containing "SomeType". If this fails, the method throws a FileNotFoundException trying lo load it. We catch that in CanLoad and return false.
It's very important that neither "Main" nor "CanLoad" have any references to that assembly at all (even after the check), or they will crash before the check (remember, the loads are done when entering a method, not on reaching the line), but "DoStuff" can reference whatever it wants.
OK, so I have the C# DLL method:
public void DeletePublisher(string strName)
{
try
{
if (_PublisherData.PublisherDictionary.ContainsKey(strName))
_PublisherData.PublisherDictionary.Remove(strName);
}
catch (Exception ex)
{
SimpleLog.Log(ex);
}
}
It works fine. If there is a exception it is detected and added to the log.
At the moment, the above is called via MFC in my C++ project using a wrapper:
bool CMSATools::DeletePublisher(CString strPublisher)
{
bool bDeleted = false;
if (m_pInterface != nullptr)
{
CComBSTR bstrPublisher = strPublisher.AllocSysString();
throw_if_fail(m_pInterface->DeletePublisher(bstrPublisher));
bDeleted = true;
}
return bDeleted;
}
They both work fine. The issue is that fact that the CPP method currently has no knowledge of the C# method having failed. Now, in this particular instance I know I could change the signature of the DLL method to return false for a exception failure occurring and examine that return value in the CPP file.
But, in other instances I am already using the return value and thus, it would seem for consistency to me, that I pass in a bool bExceptionRaised parameter instead to my methods in the DLL.
That way, I can test that value when the method seemed to complete and if it is false act accordingly.
At the moment my application doesn't realise that an exception occurred and that is confusion.
Can I assume that either of these methodologies are the simplest approach to what I am trying to detect?
Update
Based on the answer provided I have tried to follow this tutorial and I am getting confused. I have tried to follow it and I can't create a CLR DLL and build it that is a bridge to my C# DLL file.
Whilst I appreciate the answer I feel like it is breaking up everything I have worked on since the C# DLL already handles and logs it's exceptions. Whilst I would like to learn how to build this bridge for the future, I still think perhaps at the point in time just changing my signatures is sufficient. Either way, my attempt a basic build of a bridge is failing.
Use a C++/CLI wrapper for the access of the managed component.
With C++/CLI you can directly use the C# component can catch the managed exception and you can throw a native exception or even return true or false... whatever you want.
void DoManagedStuff(SOMEDATA somedata)
{
try
{
auto sm = ConvertToSomeDataToManaged(somedata);
CallManagedCode(sm);
}
catch (Exception^ e)
{
throw CMyNativeException();
}
}
I have a VS2013 C# project which references the MATLAB COM interface. 90% of what the app does is in no way related to MATLAB and I would like to be able to compile and run in environments where MATLAB is not available. The desired behavior is:
Build, regardless of presence of the reference (throwing a warning).
If MATLAB is not available, print a message if the user tries to execute MATLAB specific functionality, but it should not be fatal.
My first instinct was to use a pre-processor directive with different build configurations, but I would like to avoid this because it gets messy when setting up continuous integration and tests etc.
So I tried some reflection:
try
{
var matlab = Activator.CreateComInstanceFrom("appname.exe", "MLApp.MLApp").Unwrap();
}
catch
{
//message
}
Which throws a MissingMethodException (i.e. it cannot find a constructor). When MATLAB is present this works fine:
var matlab = new MLApp.MLApp();
New ideas most welcome, thanks in advance!
Edit:
See below for a detailed answer, but for those looking for a quick bit of test code, here is what worked for me.
var Matlab_t = Type.GetTypeFromProgID("Matlab.Autoserver");
if (Matlab_t != null)
matlab = Activator.CreateInstance(Matlab_t);
else
MessageBox.Show("Matlab installation not found.\n");
In my COM related Unit Tests / Detectors I simply do it in multiple steps:
Find COM type
Create COM object from type
Call methods.
Release COM objects, all of them.
In your case I would suggest writing mapper class hiding all of this COM ugliness under layer of abstraction. (I just needed those helpers to test COM library I wrote, so it was opposite)
Type.GetTypeFromProgID throws no exceptions when type is not found, instead it simply returns null.
public static object GetComObject(string typeName)
{
Type ComType;
ComType = Type.GetTypeFromProgID(typeName);
if (ComType == null)
{
//COM type not found
}
// Create an instance of your COM Registered Object.
return Activator.CreateInstance(ComType);
}
When object is (or is not) created I follow up with dynamic or hand-written reflections (does same stuff as dynamic but with higher degree of control, and also works in older .NET versions).
public static object CallFunction(string method, string typeName, params object[] args)
{
Type ComType;
object ComObject;
ComType = Type.GetTypeFromProgID(typeName);
if (ComType == null)
{
//COM type not found
}
// Create an instance of your COM Registered Object.
ComObject = Activator.CreateInstance(ComType);
// Call the Method and cast return to whatever it should be.
return ComType.InvokeMember(method, BindingFlags.InvokeMethod, null, ComObject, args);
}
After work is finished you should release them, all of them. Including objects returned by (created by) methods in root COM object. (Releasing parent, but not its children causes, aside of memleaks, Unit Test engine to freeze, nasty)
public static void DisposeCOM(dynamic obj)
{
if (obj != null)
{
Marshal.ReleaseComObject(obj);
}
}
quick question. I want to find out if a DLL is present in the system where my application is executing.
Is this possible in C#? (in a way that would work on ALL Windows OS?)
For DLL i mean a non-.NET classic dll (a Win32 dll)
(Basically I want to make a check cause I'm using a DLL that may or may not be present on the user system, but I don't want the app to crash without warning when this is not present :P)
Call the LoadLibrary API function:
[DllImport("kernel32", SetLastError=true)]
static extern IntPtr LoadLibrary(string lpFileName);
static bool CheckLibrary(string fileName) {
return LoadLibrary(fileName) == IntPtr.Zero;
}
When using platform invoke calls in .NET, you could use the Marshal.PrelinkAll(Type) method:
Setup tasks provide early initialization and are performed
automatically when the target method is invoked. First-time tasks
include the following:
Verifying that the platform invoke metadata is correctly formatted.
Verifying that all the managed types are valid parameters of platform
invoke functions.
Locating and loading the unmanaged DLL into the process.
Locating the entry point in the process.
As you can see, it performs additional checks other than if the dll exists, like locating the entry points (e.g if SomeMethod() and SomeMethod2() actually exist in the process like in the following code).
using System.Runtime.InteropServices;
public class MY_PINVOKES
{
[DllImport("some.dll")]
private static void SomeMethod();
[DllImport("some.dll")]
private static void SomeMethod2();
}
Then use a try/catch strategy to perform your check:
try
{
// MY_PINVOKES class where P/Invokes are
Marshal.PrelinkAll( typeof( MY_PINVOKES) );
}
catch
{
// Handle error, DLL or Method may not exist
}
Actually it does not throw FileNotFoundException.
Also for that one needs to check in multiple places for path, for the LoadLibrary
There is a standard exception in .net the is derived from TypeLoadException, that is DllNotFoundException.
Best way is to wrap a method/PInvoke call in try..catch and handle the DllNotFoundException since .net will check for application path as well as any other paths set as part of PATH OS Environment variable.
[DllImport("some.dll")]
private static void SomeMethod();
public static void SomeMethodWrapper() {
try {
SomeMethod();
} catch (DllNotFoundException) {
// Handle your logic here
}
}
Call LoadLibrary.
http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx
I'm assuming this is a PInvoke call?
If so the easiest way to make this determine if it's present is to make the call and catch the exception that results if the file does not exist.
[DllImport("some.dll")]
private static void SomeMethod();
public static void SomeMethodWrapper() {
try {
SomeMethod();
} catch (DllNotFoundException) {
// Do Nothing
}
}