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
}
}
Related
After reading quite a bit on the clipboard being blocked when trying to use it, I tried using OpenClipboard() directly, to capture the clipboard and be able to use it from my window.
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
[DllImport("user32.dll", SetLastError=true)]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError=true)]
private static extern bool CloseClipboard();
private int idx = 0;
private void refresh_Tick(object sender, EventArgs e) {
switch (idx++) {
case 0:
OpenClipboard(Handle);
break;
default:
Clipboard.SetText(" ");
break;
}
}
}
When using SetText, I will get the infamous error:
A first chance exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Windows.Forms.dll
Additional information: Requested Clipboard operation did not succeed.
So, the questions:
Does OpenClipboard() actually work?
What is the argument for OpenClipboard() for? The rest of the API does not need a handle to any window, so why does OpenClipboard()? In other words, the Clipboard is supposed to be shared between PROCESSES, not WINDOWS - but I don't see a way to lock it for my current process.
I can call OpenClipboard(IntPtr.Zero), which MSDN says:
If this parameter is NULL, the open clipboard is associated with the current task.
What is 'task' supposed to mean?
Does OpenClipboard() actually work?
OpenClipboard() works, but definitely not in the way you showed. It is a raw Win32 API. Here is an example of using it to copy string to clipboard (C/C++).
What is the argument for OpenClipboard() for?
To be honest, I'm not sure about this. Usually we just pass NULL aka IntPtr.Zero and let it associate with the current task. I guess it retrieves the thread that created the specified window, and then associates it with the clipboard.
What is task? Well here is my understanding. Back in Win16 days, instead of 'Thread' or 'Process', they used the terminology 'Task'. There was a function to GetCurrentTask().
Then the function is replaced by GetCurrentProcess() and GetCurrentThread().
Since it makes more sense that only one thread can access a shared resource at one time, I would say that 'Task' actually means 'Thread'.
The rest of the API does not need a handle to any window, so why does OpenClipboard()?
If my assumption above is correct, that is, only one thread can access Clipboard at a time, then chances are, Windows will use the thread/window you specified with OpenClipboard() previously, until you call CloseClipboard() or the thread/window becomes invalid. That's why you don't need to specify the HWND all the time.
In other words, the Clipboard is supposed to be shared between PROCESSES, not WINDOWS - but I don't see a way to lock it for my current process.
It locks, though I'm not sure about C# P/Invoke. If you have access to Win32/C development toolkit, compile and run the following code:
#include <conio.h>
#include <Windows.h>
int main()
{
OpenClipboard(GetForegroundWindow());
_getch();
return 0;
}
And see what happen if you use Clipboard in other program. :) Close the console window to restore.
I found out about the error because I saw it in the windows built-in event viewer:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.MissingMethodException
Stack:
at Injection.Main.DrawText_Hooked(...)
I have a c# application using easyhook. My dll critical code:
public void Run(RemoteHooking.IContext InContext, String InChannelName)
{
// Install system hook to detect calls to DrawTextExW that is made by the client and call the function DrawText_Hooked when ever this happens
try
{
DrawTextExHook = LocalHook.Create(LocalHook.GetProcAddress("user32.dll", "DrawTextExW"), new DDrawTextEx(DrawText_Hooked), this);
DrawTextExHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
}....
And my delegate to handle the hooked function is:
int DrawText_Hooked(...)
{
Interface.Read(hdc, lpString, cchText, dwDTFormat);
return DrawTextExW(hdc, lpString, cchText, ref lprc, dwDTFormat, ref dparams);
}
When I shut down my main application everything works fine unless I use Interface.Read(...): in this case, the hooked application crashes. I've read it's probably because Interface.Read(...) doesn't exist anymore once I exit my app but I don't know how to tell my dll to stop doing that or simply unload so that it doesn't try to do Interface.Read(...) and finds out it doesn't actually exist anymore. How shall I do it?
Two days looking for the answer and after posting it I discover it myself after 10':
What I did was to declare the hook static:
static LocalHook DrawTextExHook;
So from my main code, on exit, I could call a static method that points it to null, therefore stopping calling my Interface.Read(...).
public static void stopIt()
{
DrawTextExHook = null;
}
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.
I am working on a project that requires implementing am unmanaged windows DLL. The DLL is used to communicate with a USB device. My code is in C# and WPF.
To initialize the DLL I call a function called:
InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
When calling this function I have to pass a struct called dllInitParams and the Handle that the control is bound to.
I am using DllImport for function pointer as such:
[DllImport("myDll.dll")]
public static extern void InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
Here is my struct:
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
All of the above are in a separate class called myDllInterface.cs. Here is how I call the InitTimerDll function from my WPF form:
public IntPtr Handle
{
get { return (new System.Windows.Interop.WindowInteropHelper(this)).Handle; }
}
private void initTime_Click(object sender, RoutedEventArgs e)
{
myDllInterface.dllInitParams initParams = new myDllInterface.dllInitParams();
initParams.simp = 0;
myDllInterface.InitTimerDll(this.Handle.ToInt32(), ref initParams);
}
The first part of the above code explains how I get the handle and the initTime_Click shows how I initialize the struct, call the initTimeDll function by passing the handle and the struct to it. I have copied the dll file in the directory that the code runs in. My code compiles just fine but it creates an error when I click on the initTime button.
Error:
An unhandled exception of type 'System.AccessViolationException' occurred in ProbeCTRL.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Why is this happening?
Without knowing exactly what the InitTimerDll() function does with the 'this' pointer, I would focus on the params structure. Try adding a structure layout markup like the following:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
Also, double check that your structure is complete and accurate.
I found the problem. The code is fine the problem was the dll file, which was corrupted. A proper copy of the dll file took care of the problem. When using dll in your codes it is quite important to make sure you have accurate information, function calls, data types to passed and so on.
Thanks everyone for your help.
Have a look at the PInvoke tutorial: http://msdn.microsoft.com/en-us/library/aa288468%28v=vs.71%29.aspx
as Jim Gomes points out:
[StructLayout(LayoutKind.Sequential)]
or something similar is definitely important.
Also, you're only initializing one of the variables in your struct.
I have written a dll in C#, offering a class for use. The dll is called by a C program that I have written. (It’s a plugin to some program. I have to write the plugin’s code in C, but I want to use the functionality of .NET, therefore the dll).
In the dll, I want to open up a stream and do other stuff that should be persistent between two calls to the dll. That is represented in the following code by the private member Connector.
namespace myCSharpDll
{
// the c++ program calls this methods
public interface IAccess
{
double Initialize();
double Timestep(double time, double[] values);
...
}
// E is the beginning of another program my dll should connect to, therefore the names
public class EAccess : IAccess
{
// EConnector is another class I defined in the same dll
private EConnector Connector;
public double InitializeE()
{
Connector = new EPConnector();
}
public double Timestep(double time, double[] values)
{
return Connector.Connect();
}
When I make a call to InitializeE() and later one to Timestep() the Connector oject points to NULL.
What do I have to do that when I call Timestep() from my C code, that I can access the before created instance of Connector?
I probably search in the wrong direction at all. Any tips are appreciated.
If I am not wrong you want to maintain a single object throughout the use of dll in c. If that is the case try something similar to singleton pattern.
http://en.wikipedia.org/wiki/Singleton_pattern
What singleton emphazises is you create only single object for a class and use it to perform all the work you need. Basically you might need a function that does something like this,
public class EAccess : IAccess
{
private static EConnector Connector
public EConnector getConnector(){
if(Connector == null){
Connector = new EConnector();
}
return Connector;
}
public double Timestep(double time, double[] values)
{
return getConnector().Connect();
}
};
Even though this is not the traditional way of doing things using singleton but I think it still does the work. I may be wrong. Please correct me if I have misunderstood something.
Thanks SLaks for asking for my C/C++ code. That is where the problem was located. It was simpler than I thought. I found the mistake while putting together the code to show you.
I know that C and C++ is not the same, the plugin structure is just a little weird. Most of the code was generated by a wizard. I just had to fill in my code. It's a cpp file, but the code seems to be C. Well, I think that is off topic.
Here it is, I extraced the most important lines.
// the dll is connected via COM, using the type library file that regasm generated
#import "[path]\myCSharpDll.tlb" raw_interfaces_only
using namespace myCSharpDll;
static void OnActivate (IfmDocument, Widget);
//off topic: this are the weird lines the wizard put in my way
#ifdef __cplusplus
extern "C"
#endif /* __cplusplus */
// when the plugin is called by the host program, this function is called
static void OnActivate (IfmDocument pDoc, Widget button)
{
InitializeIntermediate(pDoc);
Timestep1(...);
}
static void InitializeIntermediate(IfmDocument pDoc)
{
// Initialize COM.
HRESULT hr = CoInitialize(NULL);
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
double result = -1;
pIEPAccess->InitializeEP (&result);
...
}
static void Timestep1(...)
{
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
double result = -1.1;
pIEPAccess->Timestep (...);
...
// now I get a wrong result back here, because this call leads to nowhere as
// the connector object in the dll is void
}
I realized that I am requesting a second instance with that line
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
So I changed that pointer to one single instance and everything is fine. Thanks for your comments!