I have a C# project in which i use several unmanaged C++ functions.
More so, I also have static IntPtr that I use as parameters for those functions. I know that whenever I use them, I should implement IDisposable in that class and use a destructor to invoke the Dispose method, where I free the used IntPtr, as is said in the MSDN page.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this.disposed)
{
if (disposing)
{
component.Dispose();
}
CloseHandle(m_InstanceHandle);
m_InstanceHandle = IntPtr.Zero;
disposed = true;
}
}
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
However, when I terminate the application, I'm still left with a hanging process in TaskManager. I believe that it must be related to the used of the MarshalAs instruction in my structures:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SipxAudioCodec
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string CodecName;
public SipxAudioBandwidth Bandwidth;
public int PayloadType;
}
When I create such a structure should I also be careful to free the space it allocs using a destructor?
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SipxAudioCodec
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string CodecName;
public SipxAudioBandwidth Bandwidth;
public int PayloadType;
~SipxAudioCodec()
{
Marshal.FreeGlobal(something...);
}
}
The proper way to handle IntPtr-style handles in p/Invoke interop is:
Define a class SafeMyHandle derived from SafeHandle. It should only override IsInvalid and ReleaseHandle, and do nothing else.
Define another class MyHandle that has methods for the public API for that handle.
MyHandle should have a private member of type SafeMyHandle.
MyHandle should implement IDisposable, and its Dispose method should just call SafeMyHandle.Dispose.
All of the p/Invoke methods should not use IntPtr directly; rather, they should pass and return instances of SafeMyHandle. The one exception is the "freeing function" that is called from SafeMyHandle.ReleaseHandle; it should take an IntPtr.
If you follow these conventions, your handles will be freed even if your AppDomain is rudely torn down.
I have had cases in the past where the application hangs after closing, usually because not all threads were terminated. How do you terminate your app? Maybe threads are the cause?
Related
I'm writing a DLL in C# that is called from Delphi using dllexport.
The basics is very simple and works, but I wanted to expose a function that returns fills a string with specific message (not returning a string). The way I'm doing it is that the Delphi sends the function a pointer of type wide string (LPWSTR) and I fill it. This works well. However, when I do it, I need to free the memory and this is where I'm not sure I did the right thing.
The DLL is build in one class that implement IDisposable. This is because I need to free the memory after the function executes.
Here is the class and this one function.
In order to release the memory I allocate, I declare a global static intPtr, which I release as dispose. Here is the code.
Would be happy to get any feedback
namespace simpleDLL
{
public class Test : IDisposable
{
public delegate int prog(int i);
static IntPtr s_copy;
bool disposed = false;
[DllExport("getString", CallingConvention = CallingConvention.Cdecl)]
public static int getString(out IntPtr s, [MarshalAs(UnmanagedType.LPWStr)] string str)
{
s_copy = (IntPtr)Marshal.StringToHGlobalUni(str);
s = s_copy;
return str.Length;
}
public void Dispose()
{
Dispose(true);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
Marshal.FreeHGlobal(s_copy);
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
~Test()
{
Dispose(false);
}
}
The following sample is from Microsoft's documentation:
public delegate bool CallBack(int handle, IntPtr param);
public class LibWrap
{
// passing managed object as LPARAM
// BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
[DllImport("user32.dll")]
public static extern bool EnumWindows(CallBack cb, IntPtr param);
}
public class App
{
public static void Main()
{
Run();
}
[SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
public static void Run()
{
TextWriter tw = System.Console.Out;
GCHandle gch = GCHandle.Alloc(tw);
CallBack cewp = new CallBack(CaptureEnumWindowsProc);
// platform invoke will prevent delegate to be garbage collected
// before call ends
LibWrap.EnumWindows(cewp, GCHandle.ToIntPtr(gch));
gch.Free();
}
private static bool CaptureEnumWindowsProc(int handle, IntPtr param)
{
GCHandle gch = GCHandle.FromIntPtr(param);
TextWriter tw = (TextWriter)gch.Target;
tw.WriteLine(handle);
return true;
}
}
There are two things that mystify me.
Firstly, the documentation of GCHandle.Alloc only talks about preventing a an object to be garbage collected. If that was all, you wouldn't need GCHandle.Alloc: Obviously in the sample, tw isn't going to be collected during the call to EnumWindows - there's a reference to it in the function scope.
The concern here is that one needs to make sure that it isn't moved. But the documentation of GCHandle.Alloc doesn't talk about that. So what's going on?
Secondly, what about the delegate? There may not be a problem in this sample, but what if the delegate is bound to an object (a lambda with a closure or a non-static method of a class)? In that case, one needs to take care of the delegate too, right? Is that another GCHandle.Alloc(myDelegate) or are there more things to consider?
Moving is not a concern. GCHandle.ToIntPtr promises to give you an integer value that you can, at a later date, pass to GCHandle.FromIntPtr to retrieve the original handle. That's all. If you need to stop the object moving in memory then you would have to pin it. But you don't actually need to pin the object, you just need to stop it being collected, and be able to retrieve it in your callback.
The delegate's lifetime is not an issue here because the p/invoke framework will make sure it is not collected during the external call to EnumWindows, as noted in the comment. If you pass a delegate to unmanaged code, and that unmanaged code holds a reference to the delegate, then you have work to do. You must ensure that the delegate outlives the unmanaged reference to it.
Following is a stripped-down version of c# code, which helps to capture the PrintScreen key. This work as I expected and tested.
Question: I am aware of deterministic destruction/disposal pattern, which I started to draft as below. However, I need some expert advice to complete my dispose and finalize method. Any advise ?
public class RegisterPrintKey : IDisposable
{
public delegate void HotKeyPass();
public event HotKeyPass HotKey;
private IntPtr m_WindowHandle = IntPtr.Zero;
private MKEY m_ModKey = MKEY.MOD_CONTROL;
private Keys m_Keys = Keys.A;
private HotKeyWndProc m_HotKeyWnd = new HotKeyWndProc();
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr wnd, int id, MKEY mode, Keys vk);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr wnd, int id);
private class HotKeyWndProc : NativeWindow
{
public int m_WParam = 10000;
public HotKeyPass m_HotKeyPass;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312 && m.WParam.ToInt32() == m_WParam)
{
if (m_HotKeyPass != null) m_HotKeyPass.Invoke();
}
base.WndProc(ref m);
}
}
private bool hasDisposed = false;
protected virtual void Dispose(bool dispose)
{
if (hasDisposed) return;
if (dispose)
{
//release objects owned by this instance
HotKey = null;
hasDisposed=true;
}
m_WindowHandle = IntPtr.Zero; // I presume this is not required.
m_Keys = null; //Do i need to dispose this or relay on stack ( clean up when thread unwind its stack)
m_ModKey = null;
m_HotKeyWnd.DestroyHandle();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~RegisterPrintKey()
{
Dispose(false);
}
}
public enum MKEY
{
MOD_ALT = 0x0001,
MOD_CONTROL = 0x0002,
MOD_SHIFT = 0x0004,
MOD_WIN = 0x0008,
}
Some suggestions on your code
public class RegisterPrintKey : IDisposable {
...
// This class can allocate the Window Handle resource (HWND)
private class HotKeyWndProc : NativeWindow {
}
// Explicit resource (HWND) allocation
private HotKeyWndProc m_HotKeyWnd = new HotKeyWndProc();
// I'd rather make a property from your "hasDisposed" field:
// - it's make easier to check instance's state (esp. while debugging)
// - IsDisposed is more popular name for this
public Boolean IsDisposed {
get;
protected set; // <- or even "private set"
}
protected virtual void Dispose(Boolean dispose) {
if (IsDisposed)
return;
if (disposed) {
// Release any Objects here
// You've allocated the HWND resource so you have to dispose it:
m_HotKeyWnd.DestroyHandle(); // <- Free HWND you've created
}
// Here, you may work with structures only!
// You don't need these assignments, but you can safely do them:
// mayhaps, they'll be useful for you while debugging
m_WindowHandle = IntPtr.Zero;
m_Keys = null;
m_ModKey = null;
// Finally, we've done with disposing the instance
IsDisposed = true;
}
public void Dispose() {
Dispose(true);
// We've done with Dispose: "GC, please, don't bother the disposed instance"
GC.SuppressFinalize(this);
}
// A treacherous enemy I've commented out:
// if you've made a error in Dispose() it'll be resource leak
// or something like AccessViolation. The only good thing is that
// you can easily reproduce (and fix) the problem.
// If you've uncommented ~RegisterPrintKey() this leak/EAV will become
// floating error: it'll appear and disappear on different workstations
// OSs etc: you can't control GC when to run. Floating error is
// much harder to detect.
// Another bad issue with finalizer is that it prevents the instance
// from being in zero generation, see
// http://stackoverflow.com/questions/12991692/why-doesnt-object-with-finalizer-get-collected-even-if-it-is-unrooted
//~RegisterPrintKey() {
// // This code can be called (if called!) at random time
// Dispose(false); // <- That's an enemy!
// }
}
The basic idea is not to touch anything managed in the Dispose(false) variant of your method. Also, there's usually no need to explicitly set anything to null (especially in the Dispose(false) variant, where those objects are probably already garbage collected).
So, you've got the basic pattern right, but you don't need to do anything in Dispose(false) except for the m_HotKeyWnd.DestroyHandle().
To explain a bit more, when the finalizer code is run by the garbage collector, all of the other managed objects referenced by this object (that aren't referenced by others) are probably garbage collected already. Ignore everything that's managed in the finalizer, it probably doesn't even exist anymore. It's also something you can expect in the native callback (ie. your WndProc in this case) - it's very much possible that the managed objects you interact with don't exist anymore, if the callback comes while the object is on the finalizer queue. This is a fairly common cause of application crashes (or at least of unexpected exceptions) in a managed application interacting with native code.
So, Dispose(true) should handle everything you want to clean up, managed and unmanaged (and you're correctly using GC.SuppressFinalize - you've already disposed of the unmanaged resources, so there's no need for GC to put your object on the finalizer queue), Dispose(false) should only ever handle the unmanaged bits.
EDIT: I didn't realize that your m_HotKeyWnd is actually a managed object - it takes care of its unmanaged resources on its own, and you should in no case call its DestroyHandle from the finalizer. In fact, you don't even need the finalizer, its completely redundant (and thus, slightly harmful). Just implement a simple Dispose (instead of the usual finalizer-dispose pattern) that disposes of the m_HotKeyWnd and sets it to null (NullReferenceException is better in this case than AccessViolationException or undefined behaviour you could get when using the object after its been disposed of - unmanaged stuff gets tricky fast), and does nothing else.
I'm in .NET 3.5, I have found
CursorInteropHelper.Create()
method here. However it is absolutely unclear how do I convert IntPtr for cursor to SafeHandle. The list of implementations of SafeHandle listed here does not include SafeCursorHandle and others are abstract or unrelated. Is the only way to go is to create my own implementation of SafeHandle?
SafeHandle is an abstract class. It wants you to provide an object of a concrete SafeHandle derived class that can release the handle. Unfortunately you forgot to mention how you obtained that IntPtr so we cannot know how it should be released.
I'll take a guess and assume it is a GDI cursor, the one you get from the CreateCursor() winapi function. Which requires calling DestroyCursor() to release the handle. Such a class could look like this:
class SafeCursorHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid {
public SafeCursorHandle(IntPtr handle) : base(true) {
base.SetHandle(handle);
}
protected override bool ReleaseHandle() {
if (!this.IsInvalid) {
if (!DestroyCursor(this.handle))
throw new System.ComponentModel.Win32Exception();
this.handle = IntPtr.Zero;
}
return true;
}
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern bool DestroyCursor(IntPtr handle);
}
Tweak the ReleaseHandle() override as necessary to release the handle in your case.
According to the MSDN doc, ReleaseHandle() must never fail:
http://msdn.microsoft.com/de-de/library/system.runtime.interopservices.safehandle.releasehandle%28v=vs.110%29.aspx
"Because one of the functions of SafeHandle is to guarantee prevention of resource leaks, the code in your implementation of ReleaseHandle must never fail."
IMO, this means that it must not throw - just like native destructors.
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.