In what cases is it better to use HandleRef instead IntPtr in PInvoke. Is there something like best practices ? I need use it in Win32 functions like GetWindow, GetWindowText, SetWindowText etc. User can close any window anytime so hwnd in not valid anymore.
For example:
1. get hwnd by function GetWindow for Notepad window
2. user close Notepad window so my hwnd is invalid
3. using this hwnd in SetWindowText will crashed
Is it possible solve this problem by HandleRef? I think no, but I am beginner in .NET.
Thanks to all :o)
VulpesPosted Jun 12, 2014, 8:05 AM
if you wrap the handle in a HandleRef rather than passing it as an IntPtr, this will ensure that the managed object is not garbage collected until the P/invoke call has completed and is therefore a sensible precaution to take in these circumstances.
However, it won't help with any of the situations you've mentioned because a Notepad window is not of course a managed object.
As there's not normally anything you can do to prevent a user from closing a window, the best thing to do is to obtain the handle each time you want to perform an operation or a series of consecutive operations rather than rely on a previously obtained handle still being valid and to always check for an error code after each operation.
Libor TheimerPosted Jun 21, 2014, 5:48 PM
Anyway, thank you
LT
VulpesPosted Jun 19, 2014, 7:34 PM
Many other books cover COM interop and Platform Invoke to some extent but I don't know of any book which covers them in the same depth as Nathan's book. It's just a pity that he never updated it.
However, I think that nowadays most .NET programmers rely on internet articles and the PInvoke.net website to cover their interop needs.
C# wrappers have been written for a lot of the more important stuff anyway and so it's no longer as important a topic as it once was.
Libor TheimerPosted Jun 19, 2014, 7:12 PM
VulpesPosted Jun 19, 2014, 8:35 AM
However, I'll just say here that the quote is from a well known book on interoperability by Adam Nathan which was published in the early days of .NET (2002). It would not therefore be any great surprise if the book contained errors or even that the GC itself contained errors which have since been corrected.
Libor TheimerPosted Jun 18, 2014, 4:05 PM
http://www.c-sharpcorner.com/Forums/Thread/258844/is-it-possible-free-obj-instance-inside-its-method.aspx
Libor TheimerPosted Jun 14, 2014, 5:40 PM
Now I understand better. I looked for a long time on the internet, but I never found examples with detailed explanations of how exactly use HandleRef. Misusing the Handleref would create the type of errors that are very difficult to find.
VulpesPosted Jun 14, 2014, 3:46 PM
The important thing is that the HandleRef is passed to the unmanaged function and the prototype for the latter needs to be declared accordingly.
The P/invoke marshaller 'knows' about the HandleRef type and will only pass the handle itself to the unmanaged function. The object reference will be used to keep the object alive until the call is completed.
Libor TheimerPosted Jun 13, 2014, 6:15 PM
Class Test
Public hdcscreen As IntPtr
Public Sub New()
hdcscreen = GetDC(IntPtr.Zero)
End Sub
Protected Overrides Sub Finalize()
Dim ret As Integer
ret = ReleaseDC(IntPtr.Zero, hdcscreen)
MyBase.Finalize()
End Sub
End Class
Sub Main()
Dim mvb As New Test()
Dim abc as Handleref = New HandleRef(mvb, mvb.hdcscreen)
Dim GrMode As Integer
GrMode = GetGraphicsMode(abc)
Console.Write(GrMode.ToString)
End Sub
VulpesPosted Jun 13, 2014, 10:50 AM
Libor TheimerPosted Jun 12, 2014, 6:30 PM
I know how use IDisposable. My question was. Is it using HandleRef in mentioned example rational? I think no, it isn't. And this example is confusing. Isn't it?
VulpesPosted Jun 12, 2014, 4:41 PM
Libor TheimerPosted Jun 12, 2014, 3:50 PM
Variable hdcscreen will exist as long as instance of class Test so why hdcscreen is HandleRef? It could be IntPtr because it is impossible to GC this variable inside instance of Test class.
And second ambiguity. hdcscreen doesn't point to managed code so it can't be GC.
I understand this correctly?