|
The EnumWindows function is a native function in Windows, you must P/Invoke it in order to call it directly in managed code. What exactly don't you understand about Heath's response, it's seems rather clear to me but if you could be more specific we would be able to help you. What he suggested will work, however I would recommend you read further about Windows hooks so you can understand the concept trying to be relayed here.
- Nick Parker My Blog | My Articles
|
|
|
|
|
hello,
yes i also think it should be better when i read further about windows hooks. do you know some good literature? and when this solution also works on a PDA this would be outstandig!! - because i search for a long time for a solution for that problem.
what do you mean with P/Invoke? - Can I take over otherwise the code in that way?
yours sincerely
patrick
|
|
|
|
|
One of the best articles I have seen is Win32 Hooks[^], however there are other articles on CP that cover this as well, do a search and read them all to get a good feel for the subject. P/Invoke is described with an example here[^].
- Nick Parker My Blog | My Articles
|
|
|
|
|
Hello,
Thank you for the references and i already read the articles and i try to reflect my thoughts - i hope they are right?
With the P/Invoke - the DLLImport i can change methods of a Dll-File, but do i need this mechanism when i use hooks? - i don't think so.
With Windows Hooks the events will be recognized before they will be executed in the application and so can be logged.
I think for my problem i need the WH_CBT Hook and the HCBT_ACTIVATE,
HCBT_CREATEWND, HCBT_DESTROYWND, HCBT_MINMAX, HCBT_MOVESIZE, HCBT_SYSCOMMAND.
With these hooks i can log when a window opens (whereby i do not exactly know the difference between activate and createwnd), a window closes, a window minimizes or maximises and when a command executes.
But now if my thoughts are right i miss the practical relation to the c# and how i can implement that.
i hope you can give me further help.
thanks in advance.
yours sincerely,
patrick
PS: I hope you know that it still concern the event logging of the PDA, where Windows Mobile 2003, Second Edition and the .NET Compact Framework is installed. I thought this method with logging the open windows and so on is the best way to know what the user do with the PDA, because that is what i want to know and this should be logged in any wise.
|
|
|
|
|
Don't you have any further tipps?
yours sincerely
patrick
|
|
|
|
|
hello,
I have spoken with an experienced developer and he was critical about the Windows Hooks on the PDA.
as i said i need this solution for a PDA (the DELL AXIM X30, Windows Mobile 2003, Second Edition;.NET Compact Framework).
Does this solution with the Hooks also work on this PDA???
yours sincerely
patrick
|
|
|
|
|
I was a little confused by your question before. No, SetWindowsHookEx is not supported on Windows Mobile, though it would be in Windows XP Embedded (but that isn't what PocketPC's run on).
EnumWindows is supported, however. Just use a Timer class (there's three in the .NET BCL to choose from, but check to make sure which ones are supported in the .NET CF) and poll for Windows. If you need to know which windows are new, keep track of existing windows in a list (like ArrayList ) or dictionary (like Hashtable ) and compare with the new list you'll obtain.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes, i first ask generally about a method to log open windows, etc. and i thought i can take this method also for windows mobile 2003 SE.
That's not good i have already read a lot about windows hooks, that's a pity that windows mobile 2003 SE don't support that.
So there is no chance to log on a PocketPC when a Window opens, destroys or a command in the window executes?
Have you got more exactly details about your solution you quoted in the previous posting?
thanks in advance.
yours sincerely,
patrick
|
|
|
|
|
I gave you the code already to enumerate windows. Just add a Timer class to your code and hook-up the appropriate event handler depending on which Timer class you use (make sure you use one supported by the .NET CF). In the handler is where you enumerate the Windows and do whatever else you need to. Make sure your timer interval is long enough that you don't have overlap when enumerating windows, otherwise you'll be a bottleneck in the system (every 5 seconds should be more than adequate).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hello,
thanks first of all for all your information!
okay i looked in the MSDN for the Timer Class and for every method it is noted if the method is supported by the .NET Compact Framework. Unfortunately at the two events tick and dispose nothing is noted - if there are supported or not...?
If the tick-event is supported by the .NET Compact Framework i would probably write the code in that way:
public class Class1 {
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
private static void TimerEventProcessor(Object myObject,
EventArgs myEventArgs) {
myTimer.Enabled = true;
[llImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr GetWindowText(IntPtr hWnd,
[Out] string title, IntPtr maxCount);
public void EnumWindows()
{
EnumWindows(new EnumWindowsProc(Callback), IntPtr.Zero);
}
private bool Callback(IntPtr hWnd, IntPtr lParam)
{
string title = new string('\0', 260);
if (GetWindowText(hWnd, title, 260)!= IntPtr.Zero)
Log(string.Format("{0:x8}: {1}", hWnd, title);
...//and here i want to save the titles of the windows in a file, do i have do consider certain things? - because when more windows are open the string title has more values one time the enumWindows-method counts the open windows?
}
}
public static int Main() {
myTimer.Tick += new EventHandler(TimerEventProcessor);
myTimer.Interval = 5000;
myTimer.Start();
Application.DoEvents();
}
return 0;
}
It would be nice if you can give me feedback to this code-fragment?
thanks in advance.
yours sincerely,
patrick
|
|
|
|
|
If ".NET Compact Framework" is not listed in the support section, then it's not supported. Use the System.Threading.Timer class instead (which takes a callback and you'll need to set it up each time - see the example).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Strange, because i already use the System.Threading.Timer - class. But appearant the tick-event is really not supported bei the CF. the only event founded which supports the CF is the dispose-event, but no example for it. Sorry but there is no example for the use of the dispose-event? - is it the same way as the tick event? - I hope i do not nerve you, but with this dispose event i do not really look through it....?
yours sincerely
patrick
|
|
|
|
|
No, actually according to the code you posted you're using the System.Windows.Forms.Timer class. Like I said, there's three Timer classes.
You have to understand that the .NET CF (Compact Framework) is slimmed-down to fit on a standard PocketPC. It lacks a lot of things that the .NET Framework for a non-Windows Mobile would have.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hello,
i know the that the .NET CF is a slimmed-down version of the .NET Framework. I found something with the callback and delegate at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemthreadingtimerclasstopic.asp.
I have to look at this exactly because for know i do not look through it how it works with the example on this site and the delegate and callback and AutoResetEvent, etc..
yours sincerely
patrick
|
|
|
|
|
Yes - that's the URL for the System.Threading.Timer class I've mentioned twice. It's the only one fully supported by the .NET CF.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hello,
i looked at delegates and TimerCallback and so on, but i don't still look really through it. I tried to write the code but i'm very insecure if this is correct.
I implement a TimeExample Class which calls the timerDelegate which calls the checkWindows method which should check which windows are open.
using System;
using System.Threading;
public class TimeExample
{
public TimeExample()
{
//
// TODO: Add constructor logic here
//
}
public static void Main()
{
AutoResetEvent autoEvent = new AutoResetEvent(false);
WindowsChecker windowsChecker = new WindowsChecker(100);
}
TimerCallback timerDelegate = new TimerCallback(windowsChecker.checkWindows);
Timer stateTimer = new Timer(timerDelegate, autoEvent, 1000, 250);
//autoEvent.WaitOne(5000, false);
//stateTimer.Dispose();
//Console.WriteLine("\nDestroying timer.");
}
--------------------------------------------------------------------------
In the WindowsChecker-class i fill in your code fragment and i defined a checkWindow-method in which should be checked which windows are open and this should be then logged in a file. For now there is only a check about the counter in the checkWindow-Method.
public class WindowsChecker
{
int invokeCount, maxCount;
public WindowsChecker(int count)
{
maxCount = count;
}
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr GetWindowText(IntPtr hWnd,
[Out] string title, IntPtr maxCount);
public void EnumWindows()
{
EnumWindows(new EnumWindowsProc(Callback), IntPtr.Zero);
}
private bool Callback(IntPtr hWnd, IntPtr lParam)
{
string title = new string('\0', 260);
if (GetWindowText(hWnd, title, 260)!= IntPtr.Zero)
Log(string.Format("{0:x8}: {1}", hWnd, title);
}
public void checkWindows (Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
++invokeCount;
if (maxCount==invokeCount)
{
invokeCount = 0;
autoEvent.Set();
}
}
}
----------------------------------------------------------------------------
I hope you can give me any further help? either i'm too stupid to solve this problem or i don't know...
thanks in advance.
yours sincerely,
patrick
|
|
|
|
|
pat270881 wrote:
either i'm too stupid to solve this problem or i don't know
This is why you read, or forever be a newbie.
You're doing several things wrong, here. First, you can't declare a variable inside one scope (i.e., method) and access it from another (like your AutoResetEvent ). You have to declare this as a field, but you can instantiate and assign an instance to that field in another method.
Second, you're instantiating your callback outside of a method. This is not supported by C# or even the CLI (the specs on which .NET is built).
To top it all off, do you even know what the AutoResetEvent is and why you're using it? You should've read about that, too. It's all in the .NET Framework SDK which should be installed locally if you took the default installation options for VS.NET, and is always available online at http://msdn.microsoft.com/library[^].
The examples you see require some understanding. They are seldom complete. Be sure to read about the Timer class and don't just rely on the examples, or you'll never learn anything.
If you were to put that original code I gave you for enumerating windows into a method, the following is roughly what you should use:
using System;
using System.Threading;
class Example
{
bool stop = false;
AutoResetEvent waitHandle;
static void Main()
{
waitHandle = new AutoResetEvent(false);
Timer t = new Timer(new TimerCallback(EnumerateWindows), null, 5000,
Timeout.Infinite);
waitHandle.WaitOne();
}
static void EnumerateWindows(object state)
{
if (stop) waitHandle.Set();
else
{
}
}
} You should definitely read about any class, property, method, etc. that you don't understand first before asking questions. The class library documentation should always be the first place you check.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hello,
thanks first for your time and effort. I have already experience with the .NET Classes, properties, methods and so on, i developed extensive WEbServices and ASP.NET Clients and ADO.NET for Database-Connectivity, but there for i needed not delegates - callbacks, the AutoResetEvent and so on, that's why these things are new for me.
Today and yesterday i read a lot about these things and i know what this things are and so on but the implementation of them is more difficult. I know that the AutoResetEvent handles the communication between the threads and the delegate wrap methods or objects and passes them to other methods but between theorie and implementation is a little difference.
Let me try to interpret your example: In the main-method you create a new AutoResetEvent-object and set it to false - means that the Event does not give up a signal to trigger. then you create a new Timer-object with the delegate-method, null, 5000 - means that in five seconds the enumerateWindows-method should first be called and the Infinite means that it is undefined when the next time the EnumerateWindows-method should be called. When the Timer-Object is created the EnumerateWindows-Method would be called and it goes further in the else tree of the method because stop is false.
I found an other example and i also tried to interpret and would ask you for correctness:
using System;
using System.Threading;
namespace ConsoleApplication8
{
class Class1
{
public void TimerCallback(Object obj)
{
Console.WriteLine("Timer triggered");
((AutoResetEvent) obj).Set();
Thread.Sleep(1000);
((AutoResetEvent) obj).Set();
}
static void Main(string[] args)
{
Class1 obj = new Class1();
AutoResetEvent ev =
new AutoResetEvent(false);
Timer timer = new Timer(
new TimerCallback(obj.TimerCallback),
ev, 1000, 0);
ev.WaitOne();
Console.WriteLine("Event Fired");
ev.WaitOne();
Console.WriteLine("Event Fired");
}
}
}
It begins in the main-method. A Class1-object and a AutoResetEvent-object which is set to false are created. Then a new Timer-Object is created - as parameters the call of the TimerCallback-method, the AutoResetEvent-object (for what do i need this parameter?) and so on. When the Timer-Object is created the TimerCallback-method is called and the Class1-object is cast to AutoResetEvent-object and is set - this means that the Event gives up a signal and the first "Event Fired" will be write out on the console. Then the thread sleeps one second and gives up a signal again and the event write out "Event Fired" a second time.
I do not know if i interpret your example and my example in a correct way? - especially for what do i need the ev.WaitOne() in my example? (I know what this method do, but why i need this method here?).
I hope you do not think i don't read in the literatur and only want that you tell me how it goes. I spent a lot of time yesterday, the day before and today to get a clear understanding about the terms i need for my implementation but it is not so easy.
i hope you will find time to help me again.
thanks in advance.
yours sincerely,
patrick
|
|
|
|
|
pat270881 wrote:
know that the AutoResetEvent handles the communication between the threads and the delegate wrap methods or objects and passes them to other methods but between theorie and implementation is a little difference.
Actually, an AutoResetEvent has little or nothing to do with threads. It's a wait handle - like a mutex - that helps synchronize threads (it can be used - though pointlessly - without threads).
A delegate is a "managed function pointer". It references only a method and allows you to synchronously or asynchronously invoke a method. This is like a CALLBACK in native C/C++, except that delegates can reference methods (functions declared on a class) unlike callbacks (has to do with the address in memory).
I'm really not sure what the other example you posted is trying to accomplish. It seems to do nothing just by looking at it. The example I posted is very much what you need.
Here's an example I threw together:
using System;
using System.Runtime.InteropServices;
using System.Threading;
class Test
{
static AutoResetEvent evt;
static int count = 1;
static void Main(string[] args)
{
if (args.Length > 0)
{
try
{
count = int.Parse(args[0]);
}
catch {}
}
evt = new AutoResetEvent(false);
Timer t = new Timer(new TimerCallback(TimerCallback), null, 0, 5000);
evt.WaitOne();
}
static void TimerCallback(object state)
{
Console.WriteLine("Enumerating windows at {0:t}...", DateTime.Now);
EnumWindows(new EnumWindowsProc(EnumWindowsCallback), IntPtr.Zero);
if (--count == 0) evt.Set();
}
static bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
{
if (hWnd != IntPtr.Zero)
{
string title = new string('\0', 260);
int ret = GetWindowText(hWnd, title, 260);
if (ret != 0)
Console.WriteLine("0x{0:x8}: {1}", hWnd.ToInt64(),
title.Substring(0, ret));
}
return true;
}
[DllImport("user32.dll")]
static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern int GetWindowText(IntPtr hWnd, [Out] string title,
int maxCount);
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I read this, because in the MSDN is noted that the AutoResetEvent handles that threads can give signalys to each other.
I hope i can interpret this sample code right:
First of all you defined a AutoResetEvent-object and an int named count.
It begins in the Main-Thread: First there is a if-call, whether a parameter was taken over at a call of the Test.cs. (This count says how often the EnumWindowsCallback-method will be executed?)
Then the AutoResetEvent evt is initialized and set to false - this means that the Event does not give up a signal to an other thread.
Then a new Timer-Object is initialized and in the course of this initialization the delegate-method will be called. (why don't you hand over the evt-object in the constructor of the Timer-object?)
What value has the TimerCallback-paramter in the constructor of the TimerCallback?
Then when the Timer-object is initialized and the TimerCallback-method is called, the today's date is write out on the console.
Then the EnumWindows-method is called. In the course of that the EnumWindowsCallback-method is called. (What values have the parameter of the EnumWindows-method?)
Within the EnumWindowsCallback-method there is a if-call - apperantly, if there are any windows open? - then the method GEtWindowText asks if the window has a title - if true the title will be write out on the console. (what means the nWnd.ToInt64() and the 0x{0:x8)?)
You see the course and order of events are still not clear for me...
I'm already afraid to ask you again for help..
yours sincerely,
patrick
|
|
|
|
|
pat270881 wrote:
why don't you hand over the evt-object in the constructor of the Timer-object?
And marshal it across thread boundaries for no reason? That's inefficient and unecessary. Just because the .NET Framework makes some things so easy does't mean you should do it that way. And passing a value type (like count ) as an object requires boxing and unboxing, which is very expensive (in terms of CPU time). Even casting reference types takes extra cycles that aren't necessary by keeping it as a field.
pat270881 wrote:
What value has the TimerCallback-paramter in the constructor of the TimerCallback?
It's the method that the delegate references. As I said before, a delegate is like a managed function pointer.
pat270881 wrote:
What values have the parameter of the EnumWindows-method?
It's in the Platform SDK for EnumWindows .
pat270881 wrote:
what means the nWnd.ToInt64() and the 0x{0:x8)?
It's in the .NET Framework SDK. Look-up IntPtr.ToInt64 and string formatting. There's no purpose explaining this if you haven't even read about it yet. If you have questions beyond that, this is the place to ask.
As far as the flow of execution you are right. The code is pretty self-explanitory if you understand the types and members used in the code.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hello,
yes i will look for this in the SDK.
But my biggest problem i still have is the Delegate-Callback mechanism? I do not simply understand how this mechanism functions, respectively in your sample code.
I read the things to delegates and TimerCallback in the MSDN and looked at the samples but i did not understand how this exactly goes?
That is for sure still my biggest problem... I do not find the logic in this mechanism..i hope i express me the right way...
yours sincerely,
patrick
|
|
|
|
|
As I've said several times, a delegate is a managed function pointer. This allows you to pass a method as a parameter and execute it without knowledge of the actual method that needs to be executed. Just like with the EnumWindows API - in native code you pass a function pointer. In .NET, you pass a delegate (a function pointer managed by the CLR). See the Delegate class in the .NET Framework SDK for more details.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
yes i know defintion of the delegate, but the thoughts behind why you build up this sample in that way is not clear.
You have explicit the EnumWindowsProc-delegate but you have not explicit declare the TimerCallback-delegate?
And why do we need the evt.WaitOne(); after the creation of the Timer-object? - the AutoResetEvent evt is already set to false.
yours sincerely,
patrick
|
|
|
|
|
The TimerCallback is a delegate that's already declared in the .NET Framework and the .NET CF. Why would I declare it? You don't re-declare the TimerCallback , you instantiate it with reference to a method that you must define. That's a delegate.
Why do I call AutoResetEvent.WaitOne ? Because the Main method has to block until signalled otherwise the application will terminate immediately since the Timer was started on a different thread. That certainly is not what you want.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|