I wish to wrap a DLL in C# - c#

The System.Windows.Forms.dll
I wish to wrap a few functions in this file in a C# class.
Specifically these: https://msdn.microsoft.com/en-us/library/system.windows.forms.cursor(v=vs.110).aspx
But I'm not sure how to get a list of functions. I've tried programs that returned no results. I was wondering if someone could give me 1 and only 1 example?
This, for example, returns an EntryPointNotFoundException
[DllImport("System.Windows.Forms.dll")]
public static extern void SetCursor(String s);

First, you need to enable interop services in order to call into windows functions:
using System.Runtime.InteropServices;
Then, you simply declare the methods that you want to import as such:
[DllImport("winmm.dll")]
public static extern bool PlaySound(string filename,long hmodule, int dword );
This creates a "mapping" to the PlaySound method in the unmanaged winmm.dll
The method is created as static and the use of the extern keywords tells the compilar that the method is external to your class (not running inside it)

To get list / search of unmanaged functions you can use
http://www.pinvoke.net
For instance, for SetCursor you can call
http://www.pinvoke.net/search.aspx?search=SetCursor&namespace=[All]
E.g. to place cursor at a position provided SetCursorPos you can do
using System.Runtime.InteropServices;
...
// Wrapper
class CursorNativeMethods {
[DllImport("User32.dll",
EntryPoint = "SetCursorPos",
CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean SetCursorPos(Point point);
...
[DllImport("User32.dll",
EntryPoint = "GetCursorPos",
CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean GetCursorPos([Out] out Point point);
...
}
// Your Routine
public static class MyCursor {
public Point Location {
get {
Point pt = new Point(-1, -1);
if (CursorNativeMethods.GetCursorPos(out pt))
return pt;
else
return new Point(-1, -1);
}
set {
CursorNativeMethods.SetCursorPos(value);
}
}
...
}
Please note, that System.Windows.Forms.dll is managed assembly (you should not interop with), and User32.dll is unmanaged library.

Related

Calling IsWowProcess2 from C# .NET (P/Invoke)

I have never created a P/Invoke wrapper method in C# because there's a way to do it "the managed way" using .NET Framework classes.
However, I have the need to invoke Win32 API function and I discovered that it's not as easy as I thought.
The function in IsWowProcess2, and the code to call it from C++ is illustrated here.
http://www.rudyhuyn.com/blog/2017/12/13/how-to-detect-that-your-x86-application-runs-on-windows-on-arm/
I've created a silly program to test it, but of course, it doesn't work:
class Program
{
static void Main(string[] args)
{
var result = IsWowProcess2();
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = false, PreserveSig = true)]
private static extern MyStruct IsWowProcess2();
}
internal class MyStruct
{
public ushort One { get; set; }
public ushort Two { get; set; }
}
What's the correct way to create the wrapper method and how to invoke it?
Start by reading the documentation. This gives the signature as:
BOOL IsWow64Process2(
HANDLE hProcess,
USHORT *pProcessMachine,
USHORT *pNativeMachine
);
As a pinvoke that is:
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool IsWow64Process2(
IntPtr process,
out ushort processMachine,
out ushort nativeMachine
);
I've no idea where your attempt came from but it looks nothing like the correct declaration, and in fact even the name of the function is wrong. Interop programming is all about detail and matching one binary interface to another. You don't get to invent the interface. Details like the parameters to be passed, the name of the function, etc. all need to match.
You can call it like this:
ushort processMachine;
ushort nativeMachine;
if (!IsWow64Process2(GetCurrentProcess(), out processMachine, out nativeMachine))
throw new Win32Exception();
You also need a declaration for GetCurrentProcess. You can use this:
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();

Using a dynamically loaded dll that contains a dynamically loaded dll itself

Intro
My program allows other developers to write plugins. These plugins(which are dll files) are placed in a certain directory and my program is able to load them at runtime like this:
Assembly assembly = Assembly.LoadFrom("MyPluginPath");
object Plugin = assembly.CreateInstance("Plugins.Main", true);
Then the program will be able to call the main method from the plugin this way:
var pluginType = Plugin.GetType();
var methodOutput = pluginType.GetMethod("MyInternalMethod").Invoke(Plugin, new object[] {param});
This works fine for all the plugins I've wrote so far that followed a certain structure as below:
namespace Plugins
{
public class Main : IDisposable
{
public Bitmap MyInternalMethod(Bitmap param)
{
// method body
}
}
}
Problem
Now there is this new plugin I've to wrote which loads an external dll at runtime itself:
namespace Plugins
{
public class Main : IDisposable
{
[System.Runtime.InteropServices.DllImport("MyExternalDLL.dll")]
unsafe private static extern int Initialize(int* arg1, char* arg2);
public Bitmap MyInternalMethod(Bitmap param)
{
// method body
Initialize(x,y);
}
}
}
Initialize(x,y) method in the above code gives me an error that says
Failed to initialize com library.
Notes
I created an executable test application for my plugin and it worked fine, so I know the problem occurs when using it as a dll at runtime.
I thought maybe I should load my external dll in the main program and then pass it as a Func<> object to my plugin but Func<> doesn't allow pointer variables (Initialize method contains arguments like int* and char*) and even if it does, I'm not sure if this solution is gonna work.
I tried using winApi as "Sinatr" suggested in the comments by following this answer but the error stays. I even tried loading MyExternalDLL.dll in the main program using winApi and passing the retrieved address of Initialize method to my plugin like the following code but the error remains the same (this way the error happens on func(x,y)):
Main program:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string name);
IntPtr dllHandle = IntPtr.Zero;
IntPtr addr = IntPtr.Zero;
private void RunPlugin()
{
dllHandle = LoadLibrary("MyExternalDLL.dll");
addr = GetProcAddress(dllHandle, "Initialize");
var methodOutput = pluginType.GetMethod("MyInternalMethod").Invoke(Plugin, new object[] {param, addr});
}
Plugin:
public class Main : IDisposable
{
private unsafe delegate byte initialize_api(int* arg1, char* arg2);
public Bitmap MyInternalMethod(Bitmap param, IntPtr addr)
{
// method body
//initialize_api is a delegate with the same signature as Initialize(x,y);
var func = (initialize_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(initialize_api));
func(x,y);
}
}
Since we are talking about plugins here, I don't think implementing a common Interface which both my program and the plugins can use is possible.
Question
Is it even possible to use a dynamically loaded dll that contains a dynamically loaded dll the way I described? if it is, what should I do to make this work?

How do you directly call a native function exported from a DLL?

How do you directly call a native function exported from a DLL? Can someone just give me a small example?
This is Microsoft example:
class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public static extern int puts(string c);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();
public static void Main()
{
puts("Test");
_flushall();
}
}
If you need to generate C# DLLImport declarations from a native dll, watch this post: Generate C# DLLImport declarations from a native dll
Depends on what exactly you want ... I have something like this in my code but this uses the Win32 API dll's
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
then just call
GetForegroundWindow()
as if defined inside the class
Here’s a quick example of the DllImport attribute in action:
using System.Runtime.InteropServices;
class C
{
[DllImport("user32.dll")]
public static extern int MessageBoxA(int h, string m, string c, int type);
public static int Main()
{
return MessageBoxA(0, "Hello World!", "Caption", 0);
}
}
This example shows the minimum requirements for declaring a C# method that is implemented in a native DLL. The method C.MessageBoxA() is declared with the static and external modifiers, and has the DllImport attribute, which tells the compiler that the implementation comes from the user32.dll, using the default name of MessageBoxA.
Refer this link

Calling multiple dll imports with the same method name

I'm importing several unmanaged c++ DLL's into my project however the imported DLLs have the same method name which causes compiler issues. For example;
unsafe class Myclass
{
[DllImport("myfirstdll.dll")]
public static extern bool ReturnValidate(long* bignum);
[DllImport("myseconddll.dll")]
public static extern bool ReturnValidate(long* bignum);
public Myclass
{
int anum = 123;
long passednum = &anum;
ReturnValidate(passsednum);
}
}
Now what I'd like to do would be rename the method on import. Something like;
[DllImport("myseconddll.dll")]
public static extern bool ReturnValidate(long bignum) AS bool ReturnValidate2(long bignum);
Is this possible?
Use the EntryPoint property of DllImport attribute.
[DllImport("myseconddll.dll", EntryPoint = "ReturnValidate")]
public static extern bool ReturnValidate2(long bignum);
Now when you call ReturnValidate2 in your C# code, you will effectively call ReturnValidate on myseconddll.dll.
You could provide any name for your imported function, you should only specify in DllImport the name of the function in it, using EntryPoint property. So you code could look like:
[DllImport("myfirstdll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate1(long bignum);
[DllImport("myseconddll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate2(long bignum);
Use the EntryPoint parameter:
[DllImport("myfirstdll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate1(long bignum);
[DllImport("myseconddll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate2(long bignum);
Documentation:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.entrypoint.aspx

P/Invoking a function with a variadic signature

I have a C#.NET 2.0 CF application that imports a function from a native DLL with the following signature:
__declspec( dllexport ) void DLL_Foo( int count, ... );
My C# application P/Invokes that function as follows:
public sealed class MyObject
{
public void Foo()
{
NativeMethods.DLL_Foo(2, __arglist("a","b"));
}
internal static class NativeMethods
{
[DllImport("My.dll")]
internal static extern void DLL_Foo(int count, __arglist);
}
}
But, when I invoke MyObject.Foo, I get a System.MissingMethodException.
What do I need to change to make this work?
Thanks,
PaulH
Edit: If I change the import definition to:
internal static extern void DLL_Foo(int count, [MarshalAs(UnmanagedType.LPWStr)]string a, [MarshalAs(UnmanagedType.LPWStr)]string b);
then, call:
NativeMethods.DLL_Foo(2, "a", "b");
It works with no problems, so it's something with my __arglist usage.
I am not sure (and I have never done it) if you can have params args in P/Invoke but you might give it a try.
internal static extern void DLL_Foo(int count, params string[] args);
You should be using CallingConvention = CallingConvention.Cdecl for your DllImport. The CallingConvention.Cdecl description states it.
using LPWORD = System.IntPtr;
using LPVOID = System.IntPtr;
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern LPVOID extFunc(LPWORD lpdwMandatory,__arglist);
And then You can call extFunc function:
extFunc(lp1,__arglist( 0xFF,0x6A,0xAA));

Categories