473,406 Members | 2,705 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Hooks, delegates and callbacks

I'm not sure whether this is a C# or C++ question, so I'm asking in both
groups.

Here's my scenario:
I need to get all text added to a ListBox that is in another process that I
have no control over. I want to get this information in my C# application
through a callback.

Here's what I've done:
Since global hooks must be done in C, I've written a simple DLL that finds
the handle of the ListBox I want the info from, hooks it, and gets the
string data as it is added. This all works just fine.

The problem:
From C# I create a delegate and pass it into the DLL prior to hooking the
ListBox. The DLL then saves the function pointer to a global variable for
use in the hook procedure. I *can* successfully call the callback from the
routine that accepts the handler. When I try to use said handle from the
hook proc, it is NULL and things go bad.

So this is basically what I've got:

#pragma data_seg(".shared")
CallBack m_callback = NULL;
#pragma data_seg()

typedef void (__stdcall *CallBack)(LPCTSTR);

__declspec(dllexport)
BOOL __stdcall LoadHook(CallBack callback)
{
// If already hooked, don't do it again.

// save the hook to a global area
m_callback = callback;

// I *CAN* call the callback here - this works:
m_callback("test");
}

LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
{
CWPSTRUCT *lpcwt;
lpcwt = (CWPSTRUCT *)lParam;

switch (lpcwt->message)
{

case LB_ADDSTRING:
// my global callback handle is ALWAYS NULL here
if(m_callback)
m_callback("test");

}
}
I've also tried using a memory-mapped file to store the callback function
pointer, but that also fails.

Is there something special about a hook proc that makes this so it can't
work?

Any pointers are GREATLY appreciated!

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net
Nov 16 '05 #1
9 1846
Are you sure you're keeping a reference to the delegate in your C# code?
Otherwise the GC will think the delegate is available for collection.

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.
Nov 16 '05 #2
It's a member variable of the C# calling class, which is a member variable
of my main app Form, so it should be valid until the form dies. Is it
possible that it's getting moved by the memory manager or something? Here
are the C# guts....

public delegate void HookCallback(string Message);

public class DataGrabber : System.Windows.Forms.Form
{
private HookClass m_hook;

....
}

public class HookClass
{
private HookCallback hookcallback;

public HookClass()
{
hookcallback = new HookCallback(HookProc);

LoadHook(hookcallback);
}

public void HookProc(string Message)
{
}

[DllImport("MyHook.dll", CallingConvention=CallingConvention.StdCall)]
internal static extern int LoadHook(HookCallback cb);
}


--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

"Grant Richins [MS]" <gr*****@online.microsoft.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Are you sure you're keeping a reference to the delegate in your C# code?
Otherwise the GC will think the delegate is available for collection.

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.

Nov 16 '05 #3
Chris,
Here's my scenario:
I need to get all text added to a ListBox that is in another process that I
have no control over. I want to get this information in my C# application
through a callback.
Do you have to get new strings when they are added to the listbox? I
think it would be easier to do a polling solution that checks for
changes in the listbox at a fixed interval.

The problem:
From C# I create a delegate and pass it into the DLL prior to hooking the
ListBox.


That won't work since the callback address is only valid in the
process space of your app, not the hooked app.

You have to find another way to pass back the information to the C#
app. Perhaps sending a WM_COPYDATA message or putting the data in a
memory mapped file.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/
Please reply only to the newsgroup.
Nov 16 '05 #4
100
Hi Chris,
Do you use /SECTION I can't seet in your code. Without that you don't share
anything

#pragma comment(linker, "/SECTION:.shared,RWS")
#pragma data_seg(".shared")
int nShared = 0;
#pragma data_seg()

HTH
B\rgds
100

"Chris Tacke, eMVP" <ct****@spamfree-opennetcf.org> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
I'm not sure whether this is a C# or C++ question, so I'm asking in both
groups.

Here's my scenario:
I need to get all text added to a ListBox that is in another process that I have no control over. I want to get this information in my C# application
through a callback.

Here's what I've done:
Since global hooks must be done in C, I've written a simple DLL that finds
the handle of the ListBox I want the info from, hooks it, and gets the
string data as it is added. This all works just fine.

The problem:
From C# I create a delegate and pass it into the DLL prior to hooking the
ListBox. The DLL then saves the function pointer to a global variable for
use in the hook procedure. I *can* successfully call the callback from the routine that accepts the handler. When I try to use said handle from the
hook proc, it is NULL and things go bad.

So this is basically what I've got:

#pragma data_seg(".shared")
CallBack m_callback = NULL;
#pragma data_seg()

typedef void (__stdcall *CallBack)(LPCTSTR);

__declspec(dllexport)
BOOL __stdcall LoadHook(CallBack callback)
{
// If already hooked, don't do it again.

// save the hook to a global area
m_callback = callback;

// I *CAN* call the callback here - this works:
m_callback("test");
}

LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
{
CWPSTRUCT *lpcwt;
lpcwt = (CWPSTRUCT *)lParam;

switch (lpcwt->message)
{

case LB_ADDSTRING:
// my global callback handle is ALWAYS NULL here
if(m_callback)
m_callback("test");

}
}
I've also tried using a memory-mapped file to store the callback function
pointer, but that also fails.

Is there something special about a hook proc that makes this so it can't
work?

Any pointers are GREATLY appreciated!

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

Nov 16 '05 #5
Yep, it's time dependent and actually must link with another thread
gathering other data at the same time, so polling won't work.

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:u4*************@TK2MSFTNGP10.phx.gbl...
Chris,
Here's my scenario:
I need to get all text added to a ListBox that is in another process that Ihave no control over. I want to get this information in my C# applicationthrough a callback.


Do you have to get new strings when they are added to the listbox? I
think it would be easier to do a polling solution that checks for
changes in the listbox at a fixed interval.

The problem:
From C# I create a delegate and pass it into the DLL prior to hooking the
ListBox.


That won't work since the callback address is only valid in the
process space of your app, not the hooked app.

You have to find another way to pass back the information to the C#
app. Perhaps sending a WM_COPYDATA message or putting the data in a
memory mapped file.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/
Please reply only to the newsgroup.

Nov 16 '05 #6
the #pragma comment line just adds a linker option without me having to go
to the project settings. The shared segment name is ".shared"

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

"100" <10*@100.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
Hi Chris,
Do you use /SECTION I can't seet in your code. Without that you don't share anything

#pragma comment(linker, "/SECTION:.shared,RWS")
#pragma data_seg(".shared")
int nShared = 0;
#pragma data_seg()

HTH
B\rgds
100

"Chris Tacke, eMVP" <ct****@spamfree-opennetcf.org> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
I'm not sure whether this is a C# or C++ question, so I'm asking in both
groups.

Here's my scenario:
I need to get all text added to a ListBox that is in another process that
I
have no control over. I want to get this information in my C#

application through a callback.

Here's what I've done:
Since global hooks must be done in C, I've written a simple DLL that finds the handle of the ListBox I want the info from, hooks it, and gets the
string data as it is added. This all works just fine.

The problem:
From C# I create a delegate and pass it into the DLL prior to hooking the ListBox. The DLL then saves the function pointer to a global variable for use in the hook procedure. I *can* successfully call the callback from

the
routine that accepts the handler. When I try to use said handle from the hook proc, it is NULL and things go bad.

So this is basically what I've got:

#pragma data_seg(".shared")
CallBack m_callback = NULL;
#pragma data_seg()

typedef void (__stdcall *CallBack)(LPCTSTR);

__declspec(dllexport)
BOOL __stdcall LoadHook(CallBack callback)
{
// If already hooked, don't do it again.

// save the hook to a global area
m_callback = callback;

// I *CAN* call the callback here - this works:
m_callback("test");
}

LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
{
CWPSTRUCT *lpcwt;
lpcwt = (CWPSTRUCT *)lParam;

switch (lpcwt->message)
{

case LB_ADDSTRING:
// my global callback handle is ALWAYS NULL here
if(m_callback)
m_callback("test");

}
}
I've also tried using a memory-mapped file to store the callback function pointer, but that also fails.

Is there something special about a hook proc that makes this so it can't
work?

Any pointers are GREATLY appreciated!

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


Nov 16 '05 #7
My only experience is using the function pointer while still inside the
original function that got passed the delegate. My best guess is that once
the function returns the runtime is tearing down the marshaled function
pointer. I would try 2 things: pass the delegate in on a new thread, so it
can block until the native function pointer is no longer needed, or try to
figure out how to use Marshal.GetUnmanagedThunkForManagedMethodPtr.

HTH

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.
Nov 16 '05 #8
Godd ideas, thanks. Right now I'm chasing an alternate method of creating a
Window in my C# app, passing it's handle down to the DLL, which then uses
WM_COPYDATA to send the data back. Of course it's not working, but
hopefully it's something I've overlooked. I can cathc a WM_USER message,
but the lParam string is empty. When I move to WM_COPYDATA, I don't get the
message. Go figure.

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

"Grant Richins [MS]" <gr*****@online.microsoft.com> wrote in message
news:OF****************@TK2MSFTNGP11.phx.gbl...
My only experience is using the function pointer while still inside the
original function that got passed the delegate. My best guess is that once the function returns the runtime is tearing down the marshaled function
pointer. I would try 2 things: pass the delegate in on a new thread, so it can block until the native function pointer is no longer needed, or try to
figure out how to use Marshal.GetUnmanagedThunkForManagedMethodPtr.

HTH

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no rights.

Nov 16 '05 #9
Well, I got the WM_COPYDATA piece working. I may go back and try to get the
callback working in the future, but the WM_COPYDATA showed an interesting
insight. If I pass in a target HWND for the WM_COPYDATA target and store it
in the shared data section it works just fine. It's just the callback
method pointer that gets destroyed. I'm thinking that you're right about
the marshaler tearing down the callback pointer.

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

"Chris Tacke, eMVP" <ct****@spamfree-opennetcf.org> wrote in message
news:O2*************@TK2MSFTNGP09.phx.gbl...
Godd ideas, thanks. Right now I'm chasing an alternate method of creating a Window in my C# app, passing it's handle down to the DLL, which then uses
WM_COPYDATA to send the data back. Of course it's not working, but
hopefully it's something I've overlooked. I can cathc a WM_USER message,
but the lParam string is empty. When I move to WM_COPYDATA, I don't get the message. Go figure.

--
Chris Tacke, eMVP
Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net

"Grant Richins [MS]" <gr*****@online.microsoft.com> wrote in message
news:OF****************@TK2MSFTNGP11.phx.gbl...
My only experience is using the function pointer while still inside the
original function that got passed the delegate. My best guess is that

once
the function returns the runtime is tearing down the marshaled function
pointer. I would try 2 things: pass the delegate in on a new thread, so

it
can block until the native function pointer is no longer needed, or try to figure out how to use Marshal.GetUnmanagedThunkForManagedMethodPtr.

HTH

--
--Grant
This posting is provided "AS IS" with no warranties, and confers no

rights.


Nov 16 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Chris Tacke, eMVP | last post by:
I'm not sure whether this is a C# or C++ question, so I'm asking in both groups. Here's my scenario: I need to get all text added to a ListBox that is in another process that I have no control...
3
by: Chua Wen Ching | last post by:
Hi there, I just read Chris Sells's article at http://www.codeproject.com/csharp/delegate_bedtime.asp?df=100&forumid=2983&select=922269#xx922269xx I wonder i can do this: 1) I want to...
4
by: LP | last post by:
Hello! I am still transitioning from VB.NET to C#. I undertand the basic concepts of Delegates, more so of Events and somewhat understand AsyncCallback methods. But I need some clarification on...
4
by: DKode | last post by:
Hello, I have a question about delegates and events I have a basic understanding of each, but in the apps I'm building I'm never needing to use these tools. I'm wondering when and where you...
2
by: Viet | last post by:
I have a couple of questions that hopefully someone could clarify for me. I have an app that uses the threading.timer to constantly poll a scanner to scan in documents. I understand that Async...
3
by: beaker | last post by:
Hello, I'm trying to make a user control which acts as a frame grabber, and I'm using the functionality in avicap32.dll to do this. I need to setup a callback function which gets called...
4
by: Frankie | last post by:
I have just gotten up to speed on what anonymous methods are (syntax, capabilities, etc), and how they can be used with /called via delegates. What I am wondering is... 1. Are they only/mostly...
6
by: =?Utf-8?B?T2xkQ2FEb2c=?= | last post by:
My question is regarding the use of delegates in C#. I see how .Net uses delegates to wire event handlers to events. It’s an object created by a single line of code by the system and that makes...
7
by: Siegfried Heintze | last post by:
I'm studying the book "Microsoft Visual Basic.NET Language Reference" and I would like some clarify the difference between events and delegates. On page 156 I see a WinForms example of timer that...
6
by: Tem | last post by:
I've read every example i could find on the subject and still couldn't figure out its proper usage. What's the point of delegates, why can't I just invoke the method directly??? Can someone...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.