How to log actions in compact framework?
I'm working on a windows mobile project using compact framework.
One thing I have to do is log when users perform actions, this can mean any action from pressing a button to using the barcode scanner. The time it happened also needs to be logged.
My plan is to override all controls to include logging functionality built into them but this might not be the right way to go about it, seems like a very tedious thing to do..
Is there a better way?
I would go with IL Weaving. Here is a library that I would recommend: http://www.sharpcrafters.com/aop.net/msil-injection What it does is that you mark your class with an attribute and you can intercept all function calls. In this interception you would put in your logging logic.
I'd say it depends greatly on the definition of "action". I'd be highly inclined to see if the (undocumented) QASetWindowsJournalHook
API would work. It's probably going to grab most of what you want, with not a lot of code required. A native example of usage can be found on Codeproject here.
SetWindowsHook with WH_JOURNALRECORD
might also be worth a look. Yeah, I know it's "unsupported" but it works just fine, and it's unlikely to be removed from a device you've got fielded (plus it's been in the OS for at least 10 years).
Some P/Invoke declarations, all derived from pwinuser.h, for them both are as follows:
[StructLayout(LayoutKind.Sequential)]
public struct JournalHookStruct
{
public int message { get; set; }
public int paramL { get; set; }
public int paramH { get; set; }
public int time { get; set; }
public IntPtr hwnd { get; set; }
}
internal enum HookType
{
JournalRecord = 0,
JournalPlayback = 1,
KeyboardLowLevel = 20
}
internal enum HookCode
{
Action = 0,
GetNext = 1,
Skip = 2,
NoRemove = 3,
SystemModalOn = 4,
SystemModalOff = 5
}
public const int HC_ACTION = 0;
public const int LLKHF_EXTENDED = 0x1;
public const int LLKHF_INJECTED = 0x10;
public const int LLKHF_ALTDOWN = 0x20;
public const int LLKHF_UP = 0x80;
public const int VK_TAB = 0x9;
public const int VK_CONTROL = 0x11;
public const int VK_ESCAPE = 0x1B;
public const int VK_DELETE = 0x2E;
[DllImport("coredll.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(HookType idHook, HookProc lpfn, IntPtr hMod, int
[DllImport("coredll.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("coredll.dll", SetLastError = true)]
public static extern int CallNextHookEx(IntPtr hhk, HookCode nCode, IntPtr wParam, IntPtr
[DllImport("coredll.dll", SetLastError = true)]
public static extern IntPtr QASetWindowsJournalHook(HookType nFilterType, HookProc pfnFilterProc, ref JournalHookStruct pfnEventMsg);
Would writing these messages to a log file not solve your problem?
#if PocketPC
private static string _appPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
#else
private static string _appPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Application.CompanyName);
#endif
public const int KILOBYTE = 1024;
public static string ErrorFile { get { return _appPath + @"error.log"; } }
public static void Log(string message)
{
if (String.IsNullOrEmpty(message)) return;
using (FileStream stream = File.Open(ErrorFile, FileMode.Append, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(stream, Encoding.UTF8, KILOBYTE))
{
sw.WriteLine(string.Format("{0:MM/dd/yyyy HH:mm:ss} - {1}", DateTime.Now, message));
}
}
}
You could have issues though if you have threading going on and multiple routines try to write at the same time. In that case, you could add additional logic to lock the routine while it is in use.
That's how I do it, anyway.
By the #if
regions, you can see this is also used by my Windows PC applications.
上一篇: 如何手动滚动面板?
下一篇: 如何在紧凑框架中记录操作?