|
Use a DataSet as the data source. Fill your DataSet with what you need from the Jet database (MDB) and pass it to SetDataSource . In the Cyrstal Reports designer, you can bind against a DataSet but it helps to use a typed DataSet , which xsd.exe or the DataSet designer in VS.NET can do easily.
If you have a view, table, or tables that you want to fill the DataSet with, connect the Jet database in the Server Explorer, browse to the view or table(s), and drag and drop them into a new DataSet item you can add to your project. This will create the necessary elements for you.
Then in the Crystal Reports designer, you can add a reference to that typed DataSet and design your report as you would normally.
This makes for a good disconnected architecture since it doesn't matter from where that data is obtained (could be a Jet database, SQL Server, Oracle, an XML file, etc.).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hi,
does anybody know how i can scan and/or log in a file, that e.g. for all 5 seconds or when a window opens, it would be logged in a file, which windows are opened?(the title of the window or something else) i need this mechanism for usability tests.
i hope someone can help me.
thanks in advance
yours sincerely
patrick
|
|
|
|
|
i know can also be not a C# specific question but it anybody knows a solution with c# it would be c#-specific. the best case were if anybody know a tool with which i can solve the quoted problem??
thanks in advance.
patrick
|
|
|
|
|
Enumerating the top-level windows is easy: P/Invoke the EnumWindows native API:
[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);
} If instead of windows you want to enumerate all running processes (and perhaps filter those that do not have application windows), you can use Process.GetProcesses and, optionally, check if Process.MainWindowHandle is IntPtr.Zero (not graphical).
Responding when a window opens is a bit more tricky. You must efficiently implement a Windows hook and handle the WH_CBT (0x05) message. This message is documented in the Platform SDK along with related APIs like SetWindowsHookEx . The callback (CBTProc ) is called whenever a window is about to be activated, created, destroyed, minimized, maximized, moved, or resized (so you'll need to filter these appropriately based on your needs).
You can read more about implementing windows hooks in .NET (using the C# language) by reading Using Hooks from C#[^] here on this site. Any questions specific to this article should be directed to the article's message board at the bottom of the page.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hello,
thank you for your reply, unfortunately i do not really know what you mean with your solution, although i thought i have good experience in c#, ado.net, asp.net, etc.
the situation is as follows: i want to log the events on a PDA (DELL AXIM X30 Windows Mobile 2003, Second Edition, .NET Compact Framework), like when a user makes an entry in the time planner,..etc. So it should be recorded if a window opens, respectively what window opens, etc.
is this possible with your idea? - and can you probably explain me your solution in a simpler way? i also read the article "Using hooks from c#" but i do also not look through it.
i hope you can help me once more, because i would need this for a Thesis (diploma).
thanks in advance.
yours sincerely
patrick
|
|
|
|
|
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
|
|
|
|
|