473,385 Members | 1,449 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,385 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 15 '05 #1
9 5710
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 15 '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 15 '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 15 '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 15 '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 15 '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 15 '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 15 '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 15 '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 15 '05 #10

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

Similar topics

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...
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...
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...
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
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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...

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.