static class Class
{
public static void methodRequiringStuffFromKernel32()
{
// code here...
}
}
Where do I put [DllImport("Kernel32.dll")] here?
You put it on the method you're importing from Kernel32.dll.
For example,
static class Class
{
[DllImport("Kernel32.dll")]
static extern Boolean Beep(UInt32 frequency, UInt32 duration);
public static void methodRequiringStuffFromKernel32()
{
// code here...
Beep(...);
}
}
From #dtb: Note that the class should be named NativeMethods, SafeNativeMethods or UnsafeNativeMethods. See Naming Convention for Unmanaged Code Methods for more details.
CA1060: Move P/Invokes to NativeMethods class:
NativeMethods - This class does not suppress stack walks for unmanaged code permission. (System.Security.SuppressUnmanagedCodeSecurityAttribute must not be applied to this class.) This class is for methods that can be used anywhere because a stack walk will be performed.
SafeNativeMethods - This class suppresses stack walks for unmanaged code permission. (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) This class is for methods that are safe for anyone to call. Callers of these methods are not required to perform a full security review to make sure that the usage is secure because the methods are harmless for any caller.
UnsafeNativeMethods - This class suppresses stack walks for unmanaged code permission. (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) This class is for methods that are potentially dangerous. Any caller of these methods must perform a full security review to make sure that the usage is secure because no stack walk will be performed.
This is an example of DllImport:
using System;
using System.Runtime.InteropServices;
class MsgBoxTest
{
[DllImport("user32.dll")]
static extern int MessageBox (IntPtr hWnd, string text, string caption,
int type);
public static void Main()
{
MessageBox (IntPtr.Zero, "Please do not press this again.", "Attention", 0);
}
}
I suggest you to study Platform Invoke Tutorial.
static class Class
{
[DllImport("kerynel32.dll")]
public static extern void methodRequiringStuffFromKernel32();
}
It goes on the method itself that's P/Invoking outside methods. Make sure to add a reference to System.Runtime.InteropServices
Related
For example this is what i need:
using System.Runtime.InteropServices;
using System;
public class Prog
{
public static Type myType = typeof(IntPtr);
public static void Main() {
var handle = new IntPtr(12345);
SetForegroundWindow(handle);
}
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(myType hWnd);
}
How to write it down correctly? Visual studio underlines myType in method import.
In this case, Type is an IntPtr, so I would think:
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
is enough to PInvoke the SetForegroundWindow method. This is a static API and the compiler doesnt need reflection to bind to it, it just wants to know the contract to that API, which in this case just takes a single IntPtr to the window handle.
When you declare
public static Type myType = typeof(IntPtr);
you are creating a variable (statically) named myType which holds the type information for the type IntPtr. That information cant really be used in a method signature, its more useful in runtime reflection scenarios. In order to use an IntPtr in your method signature you need to use the actual type in the parameter declaration.
I wan to import a DLL and use its functions but i want to assign the dll to a value so i dont end up overiding methods
Example of how I want to do it
mydll = [DllImport("MyDll.dll")]
mydll.SayHi();
// So I don't override this:
public void SayHi() { Console.WriteLine("Hello!!!"); }
Any way to acheive this?
Import the DLL in a wrapper class.
using System;
using System.Runtime.InteropServices;
// Namespace is optional but generally recommended.
namespace MyDLLImports
{
static class MyDLLWrapper
{
// Use DllImport to import the SayHi() function.
[DllImport("mydll.dll", CharSet = CharSet.Unicode)]
public static extern void SayHi();
}
}
class Program
{
static void SayHi()
{
// whatever...
}
static void Main()
{
// Call the different SayHi() functions.
MyImports.MyDLLWrapper.SayHi();
SayHi();
}
}
See the MSDN docs on the DLLImport attribute for further details. You may also need to declare calling conventions, different character encodings, the DLL's main entry point, etc.
I have a problem with the glfwSetCharCallback function. Whenever I call it, the glfwPollEvents throws an AccessViolationException saying: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
I have created a very simple wrapper just to demonstrate the problem:
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace Test
{
public delegate void GlfwCharCallback(GlfwWindow window, Char character);
[StructLayout(LayoutKind.Explicit)]
public struct GlfwMonitor
{
private GlfwMonitor(IntPtr ptr)
{
_nativePtr = ptr;
}
[FieldOffset(0)] private readonly IntPtr _nativePtr;
public static readonly GlfwMonitor Null = new GlfwMonitor(IntPtr.Zero);
}
[StructLayout(LayoutKind.Explicit)]
public struct GlfwWindow
{
private GlfwWindow(IntPtr ptr)
{
_nativePtr = ptr;
}
[FieldOffset(0)] private readonly IntPtr _nativePtr;
public static GlfwWindow Null = new GlfwWindow(IntPtr.Zero);
}
public class Wrap
{
[DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
private static extern Int32 glfwInit();
[DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
internal static extern GlfwWindow glfwCreateWindow(Int32 width, Int32 height,
[MarshalAs(UnmanagedType.LPStr)] String title,
GlfwMonitor monitor, GlfwWindow share);
[DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
internal static extern void glfwSetCharCallback(GlfwWindow window, GlfwCharCallback callback);
[DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
internal static extern void glfwPollEvents();
public static Boolean Init()
{
return glfwInit() == 1;
}
public static GlfwWindow CreateWindow(Int32 width, Int32 height, String title, GlfwMonitor monitor,
GlfwWindow share)
{
return glfwCreateWindow(width, height, title, monitor, share);
}
public static void SetCharCallback(GlfwWindow window, GlfwCharCallback callback)
{
glfwSetCharCallback(window, callback);
}
public static void PollEvents()
{
glfwPollEvents();
}
}
}
And I call it like I would GLFW:
using System;
namespace Test
{
class Program
{
static void Main()
{
Wrap.Init();
var window = Wrap.CreateWindow(800, 600, "None", GlfwMonitor.Null, GlfwWindow.Null);
Wrap.SetCharCallback(window, (glfwWindow, character) => Console.WriteLine(character));
while(true)
{
Wrap.PollEvents();
}
}
}
}
The character is printed into the console and I get the AccessViolationException.
What am I doing incorrectly? All the DllImports specify the CDecl calling convention (I've tried the others on both PollEvents and SetCharCallback), I've tried all CharSets on the SetCharCallback function and nothing worked.
Could someone please help me?
Edit:
Here is the GLFW3 Dll that I'm using:
http://www.mediafire.com/?n4uc2bdiwdzddda
Edit 2:
Using the newest "lib-msvc110" DLL made glfwSetCharCallback work. glfwSetKeyCallback and glfwSetCursorPosCallback do not work and continue to throw AccessViolationException. I will attempt to figure out what makes CharCallback so special, but honestly, I've gone through the GLFW source code through and through and all the functions seem to do their thing in the same way. Maybe there's something I'm overlooking.
Edit 3:
I've tried everything, cdecl, stdcall, all the charsets, all versions of the dll, all combinations of arguments, etc. I've made sure that the callbacks are not disposed by storing a reference to them. I've also tried to purposefully crash the application by not reserving any space of arguments of glfwSetCharCallback (which works as of now) and I haven't managed to do it. This leads me to believe that the arguments themselves have no bearing on the application.
The thing that really makes me think the fault is with GLFW itself is the fact that if I compile against the x86-64 dll, everything works perfectly. It is a little bit strange to use cdecl on x86-64, because MSDN specifically states that the only calling convention is fastcall.
It took me a while, but I solved it. All the delegates are describing C# functions, which cannot be called from C. The solution is to make the delegates describe C-like functions, which can be achieved via the UnmanagedFunctionPointer attribute.
Adding the attribute to all delegates (as shown below) solved the problem.
[UnmanagedFunctionPointer(CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public delegate void GlfwCharCallback(GlfwWindow window, Char character);
Currently I'm trying to use a C++ library under C# using DLL importation. Library is called Interception.
The problem is that I don't know how to translate #define entries and typedef declaration of the header file:
https://github.com/oblitum/Interception/blob/master/include/interception.h
I tried to use "using" directive, but with no success (I can't access to the void definition).
Moreover, I didn't understood the role of __declspec(dllimport) in this header. In my c# project, I just ignored it? Is it good to do that?
This is the code I want to use in c# (it's a sample of the library)
https://github.com/oblitum/Interception/blob/master/samples/hardwareid/main.cpp
EDIT:
What I've tried: basic importation:
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
void interception_set_filter(void* context, InterceptionPredicate predicate, ushort filter);
I don't know ho to convert InterceptionPredicate. According the header file, InterceptionFilter is a ushort, and InterceptionContext is a void pointer (void*).
The C++ library should be compiled as a .DLL file. This .DLL file should have exported functions. You can use the Depends tool to check what's exported from a .DLL. .NET code can call C++ exported functions using what's called "Platform Invoke".
Now, I strongly suggest you take a deep look at this Platform Invoke Tutorial that will guide you.
PS: void * should be declared in c# as IntPtr. enums should be redeclared as enums. Functions should be declared as static extern methods marked with the DllImport attribute.
First, it looks like you're trying to implement a global keyboard/mouse hook .. if that's the case, I'd recommend googling 'C# low level keyboard and mouse hook'.
Now for your question, first is the __declspec(dllimport) issue: this would be if you were actually using the header in a C++ application, that is the C++ equivilent of the C# DllImport .. so in effect you didn't ignore it, you implemented it. In C++ it just tells the linker that the function declared as such will be imported from a specific DLL instead of it being a local function (pretty similar to what the C# DllImport directive does)
Next is for function pointer issue (InterceptionPredicate). In the header it is defined as such:
typedef int (*InterceptionPredicate)(InterceptionDevice device);
And InterceptionDevice is just an 'int'. So the InterceptionPredicate is just a function pointer type (or Delegate in C#), so your delegate definition for InterceptionPredicate would look like this:
// [UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate int InterceptionPredicate (int device);
A note about the UnmanagedFunctionPointer calling convention descriptor: IF you know what kind of calling convention (stdcall, fastcall, cdecl) the exported function might be using, you could specify here so that the .NET marshaler will know how to pass the data between the managed/unmanaged code, but if you don't know it or it's not specified typically you can just leave that off.
Also, as others have mentioned, unless you have the 'unsafe' flag specified in your C# properties, a void* type should always be an IntPtr in C#.
Also, be sure to mark the dll function in your C# code as public static extern, see example below.
So to make an example of the function you've specified, here's what could be done:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace InterceptorTest
{
public class Interceptor : IDisposable
{
#region DllImports
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr interception_create_context();
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void interception_destroy_context(IntPtr context);
[DllImport("interception.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void interception_set_filter(IntPtr context, InterceptionPredicate predicate, ushort filter);
// The function pointer type as defined in interception.h that needs to be defined as a delegate here
public delegate int InterceptionPredicate(int device);
#endregion
#region private members
private InterceptionPredicate m_PredicateDelegate { get; set; }
private IntPtr m_Context { get; set; }
#endregion
#region methods
public Interceptor(ushort filter)
{
// be sure to initialize the context
this.m_PredicateDelegate = new InterceptionPredicate(this.DoSomethingWithInterceptionPredicate);
this.m_Context = interception_create_context();
interception_set_filter(this.m_Context, this.m_PredicateDelegate, filter);
}
private void Cleanup()
{
interception_destroy_context(this.m_Context);
// the next line is not really needed but since we are dealing with
// managed to unmanaged code it's typically best to set to 0
this.m_Context = IntPtr.Zero;
}
public void Dispose()
{
this.Cleanup();
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing) { this.Cleanup(); }
}
public int DoSomethingWithInterceptionPredicate(int device)
{
// this function is something you would define that would do something with
// the device code (or whatever other paramaters your 'DllImport' function might have
// and return whatever interception_set_filter is expecting
return device;
}
#endregion
}
static class Program
{
[STAThread]
private static void Main(string[] argv)
{
Interceptor icp = new Interceptor(10);
// do something with the Interceptor object
}
}
}
Hope that gets you on the right track.
Ok, I found an example code that was hidden on the GIT. Thank you google!
https://gist.github.com/1959219
It precises all function from DLL importation, with a working example.
I am using DllImport in my solution.
My problem is that I have two versions of the same DLL one built for 32 bit and another for 64 bit.
They both expose the same functions with identical names and identical signatures.
My problem is that I have to use two static methods which expose these and then at run time use IntPtr size to determine the correct one to invoke.
private static class Ccf_32
{
[DllImport(myDllName32)]
public static extern int func1();
}
private static class Ccf_64
{
[DllImport(myDllName64)]
public static extern int func1();
}
I have to do this because myDllName32 and myDllName64 must be constant and I have not found a way to set it at run time.
Does anyone have an elegant solution for this so I could get rid of the code duplication and the constant IntPtr size checking.
If I could set the file name, I would only have to check once and I could get rid of a ton of repeated code.
I prefer to do this by using the LoadLibrary call from kernel32.dll to force a particular DLL to load from a specific path.
If you name your 32-bit and 64-bit DLLs the same but placed them in different paths, you could then use the following code to load the correct based on the version of Windows you are running. All you need to do is call ExampleDllLoader.LoadDll() BEFORE any code referencing the ccf class is referenced:
private static class ccf
{
[DllImport("myDllName")]
public static extern int func1();
}
public static class ExampleDllLoader
{
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
private extern static IntPtr LoadLibrary(string librayName);
public static void LoadDll()
{
String path;
//IntPtr.Size will be 4 in 32-bit processes, 8 in 64-bit processes
if (IntPtr.Size == 4)
path = "c:/example32bitpath/myDllName.dll";
else
path = "c:/example64bitpath/myDllName.dll";
LoadLibrary(path);
}
}
You can probably achieve this with the #if keyword. If you define a conditional compiler symbol called win32, the following code will use the win32-block, if you remove it it will use the other block:
#if win32
private static class ccf_32
{
[DllImport(myDllName32)]
public static extern int func1();
}
#else
private static class ccf_64
{
[DllImport(myDllName64)]
public static extern int func1();
}
#endif
This probably means that you can remove the class wrapping that you have now:
private static class ccf
{
#if win32
[DllImport(myDllName32)]
public static extern int func1();
#else
[DllImport(myDllName64)]
public static extern int func1();
#endif
}
For convenience, I guess you could create build configurations for controlling the compilation symbol.
I know this is a really old question (I'm new - is it bad to answer an old question?), but I just had to solve this same problem. I had to dynamically reference a 32-bit or 64-bit DLL based on OS, while my .EXE is compiled for Any CPU.
You can use DLLImport, and you don't need to use LoadLibrary().
I did this by using SetDLLDirectory. Contrary to the name, SetDLLDirectory adds to the DLL search path, and does not replace the entire path. This allowed me to have a DLL with the same name ("TestDLL.dll" for this discussion) in Win32 and Win64 sub-directories, and called appropriately.
public partial class frmTest : Form
{
static bool Win32 = Marshal.SizeOf(typeof(IntPtr)) == 4;
private string DLLPath = Win32 ? #"\Win32" : #"\Win64";
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetDllDirectory(string lpPathName);
[DllImport("TestDLL.dll", SetLastError = true)]
static extern IntPtr CreateTestWindow();
private void btnTest_Click(object sender, EventArgs e)
{
string dllDir = String.Concat(Directory.GetCurrentDirectory(), DLLPath);
SetDllDirectory(dllDir);
IntPtr newWindow = CreateTestWindow();
}
}
Why not wrap them into a method?
private static class ccf_32_64
{
private static class ccf_32
{
[DllImport(myDllName32)]
private static extern int func1();
}
private static class ccf_64
{
[DllImport(myDllName64)]
private static extern int func1();
}
public static int func1()
{
if (32bit)
{
return ccf_32.func1();
}
else
{
return ccf_64.func1();
}
}
}
One alternative option is to have both the 32- and 64-bit versions of the unmanaged DLL have the same name, but have them live in separate folders in your build output (say, x86\ and x64\).
Then, your installer or however else you're distributing this is updated so it knows to install the proper DLL for the platform it's installing on.
you can create two methods and choose one in a runtime, so you can keep Any CPU
public static class Ccf
{
[DllImport(myDllName32)]
private static extern int func32();
[DllImport(myDllName64)]
private static extern int func64();
public static int func()
{
if(Environment.Is64BitProcess)
{
return func64();
}
return func32();
}
}
You can't do this the way you want. You need to think of the DllImport attribute as metadata that is used at compile time. As a result you can't change the DLL it is importing dynamically.
If you want to keep your managed code targeted to "Any CPU" then you either need to import both the 32-bit and 64-bit libraries wrapped as two different functions that you can call depending on the runtime environment or use some additional Win32 API calls to late-load the correct version of the unmanaged assembly at runtime and additional Win32 calls to execute the required methods. The drawback there is that you won't have compile time support for any of that type of code for type safety, etc.
Hmm, I'm wondering if you could create an interface and then a class with the methods based on the 32 bit and 64 bit dlls.
I'm not sure if there is an explicit method to determine if you are running 64 bit, but the following might work: allow unsafe code and have an unsafe function that gets a pointer to some address and then determine whether the pointer is 4 or 8 bytes in size. Based on the result determine which implementation of the interface to create.
You can determine whether you are running 64Bits or not by checking the size of the IntPtr type (which is called native int anyways).
Then you can load the approriate DLL using an imported LoadLibraryW call, get the function pointer using GetProcAddress, and then, check out Marshal.GetDelegateForFunctionPointer
This not nearly as complicated as it might look like. You have to DllImport both LoadLibraryW and GetProcAddress.