[program-l] Re: C#: creating a service that logs mouse and keyboard input
- From: "Will Pearson" <will-pearson@xxxxxxxxxxxxx>
- To: <program-l@xxxxxxxxxxxxx>
- Date: Thu, 3 Aug 2006 15:29:50 +0100
Hi Pranav,
Your problem is related to window stations and desktops. Windows contains a
type of kernel object known as a window station, which can be thought of as
a security boundary. Each window station contains a clipboard, an atom
table, and a collection of desktops. Typically a new window station is
created for each account that is running. This is where your first problem
is occuring, and that is services and the current user, known as the
interactive user, run using different window stations. This means the
service and the user will be using different desktops.
Window messages can only be sent between windows on the same desktop and
hooks can only intercept messages sent to processes running on the same
desktop as the hook process is running on. This means that services that
contain hooks cannot ordinarily intercept things like keyboard input because
they are running on a different desktop. It's also the reason why services
can't ordinarily draw a visible UI.
In order to get the hook to work you need the process containing the hook to
be running on the desktop of the interactive user. There's two ways to do
this. The first is to forget about running as a service and run as a normal
windows app, maybe from the system tray. The second, and a technique that
is not recommended, is to run the service as an interactive service. This
is not recommended for security reasons. The service is likely to be
running under the local system account, which has admin level privileges.
As the service would be running on the same desktop as the user any UI it
exposed would be able to receive window messages from any app running on
that desktop. This combination can have some pretty nasty effects and has
been the source of attacks in the past, although since them Microsoft have
done some work.
Will
----- Original Message -----
From: "Pranav Lal" <pranav.lal@xxxxxxxxx>
To: <program-l@xxxxxxxxxxxxx>
Sent: Thursday, August 03, 2006 12:51 PM
Subject: [program-l] C#: creating a service that logs mouse and keyboard
input
Hi all,
I am trying to write an aplication in c# that logs all keystrokes to a
file. The application uses a global system hook. The program runs as
expected when I run it as a Windows application. I have tried to
convert the application to run as a service. This is not working. The
application runs but the key logging does not happen. I could be doing
something wrong when running it as a service. I will paste that code
at the end of the message. As far as I can tell, no exceptions are
thrown.
Jaws and een Narrator become sluggish when I run the service so I am
wondering whether screen readers and the application are not getting
along. I have tried tracing through the code but Visual Studio 2005
locks up when I reach the line installing the keyboard hook.
(actHook.KeyDown += new KeyEventHandler(MyKeyDown);) Mind you, the
task manager still shows Visual Studio as running. This does not
happen when I run the application as a windows application.
Note:
I have used threading which has improved the performance of the app
but I am missing something since the logging is not happening.
I have read http://www.albahari.com/threading/ for threading and
several articles over the web while creating this application.
The code for creating the global hooks has been taken from
http://www.codeproject.com/csharp/globalhook.asp I have created the
windows service after referencing
http://www.codeproject.com/csharp/WindowsService.asp.
Note:
I am using Visual studio .net (express) 2005.
Pranav
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using gma.System.Windows;
namespace WindowsService
{
class WindowsService : ServiceBase
{
UserActivityHook actHook;
Thread t;
/// <summary>
/// Public Constructor for WindowsService.
/// - Put all of your Initialization code here.
/// </summary>
public WindowsService()
{
this.ServiceName = "keyLog";
this.EventLog.Source = "KeyLog";
this.EventLog.Log = "Application";
// These Flags set whether or not to handle that specific
// type of event. Set to true if you need it, false otherwise.
this.CanHandlePowerEvent = true;
this.CanHandleSessionChangeEvent = true;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.CanStop = true;
if (!EventLog.SourceExists("My Windows Service"))
EventLog.CreateEventSource("My Windows Service",
"Application");
}
/// <summary>
/// The Main Thread: This is where your Service is Run.
/// </summary>
static void Main()
{
ServiceBase.Run(new WindowsService());
}
/// <summary>
/// Dispose of objects that need it here.
/// </summary>
/// <param name="disposing">Whether or not disposing is going
on.</param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
/// <summary>
/// OnStart: Put startup code here
/// - Start threads, get inital data, etc.
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
base.OnStart(args);
actHook = new UserActivityHook(); // crate an instance
with global hooks
actHook.OnMouseActivity += new MouseEventHandler(MouseMoved);
actHook.KeyDown += new KeyEventHandler(MyKeyDown);
actHook.KeyPress += new KeyPressEventHandler(MyKeyPress);
actHook.KeyUp += new KeyEventHandler(MyKeyUp);
t = new Thread(delegate() { actHook.Start(); });
t.IsBackground = true;
t.Start();
//actHook.Start();
}
/// <summary>
/// OnStop: Put your stop code here
/// - Stop threads, set final data, etc.
/// </summary>
protected override void OnStop()
{
base.OnStop();
actHook.Stop();
}
/// <summary>
/// OnPause: Put your pause code here
/// - Pause working threads, etc.
/// </summary>
protected override void OnPause()
{
actHook.Stop();
base.OnPause();
}
/// <summary>
/// OnContinue: Put your continue code here
/// - Un-pause working threads, etc.
/// </summary>
protected override void OnContinue()
{
base.OnContinue();
actHook.Start();
}
/// <summary>
/// OnShutdown(): Called when the System is shutting down
/// - Put code here when you need special handling
/// of code that deals with a system shutdown, such
/// as saving special data before shutdown.
/// </summary>
protected override void OnShutdown()
{
actHook.Stop();
LogWrite("shutdown detected");
base.OnShutdown();
}
/// <summary>
/// OnCustomCommand(): If you need to send a command to your
/// service without the need for Remoting or Sockets, use
/// this method to do custom methods.
/// </summary>
/// <param name="command">Arbitrary Integer between 128 &
256</param>
protected override void OnCustomCommand(int command)
{
// A custom command can be sent to a service by using this
method:
//# int command = 128; //Some Arbitrary number between 128 &
256
//# ServiceController sc = new
ServiceController("NameOfService");
//# sc.ExecuteCommand(command);
base.OnCustomCommand(command);
}
/// <summary>
/// OnPowerEvent(): Useful for detecting power status changes,
/// such as going into Suspend mode or Low Battery for laptops.
/// </summary>
/// <param name="powerStatus">The Power Broadcase Status
(BatteryLow, Suspend, etc.)</param>
protected override bool OnPowerEvent(PowerBroadcastStatus
powerStatus)
{
return base.OnPowerEvent(powerStatus);
}
/// <summary>
/// OnSessionChange(): To handle a change event from a
Terminal Server session.
/// Useful if you need to determine when a user logs in
remotely or logs off,
/// or when someone logs into the console.
/// </summary>
/// <param name="changeDescription"></param>
protected override void
OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
}
public void MouseMoved(object sender, MouseEventArgs e)
{
if (e.Clicks > 0) LogWrite("MouseButton - " +
e.Button.ToString());
}
public void MyKeyDown(object sender, KeyEventArgs e)
{
LogWrite("{" + e.KeyData.ToString()+"}");
}
public void MyKeyPress(object sender, KeyPressEventArgs e)
{
LogWrite("KeyPress - " + e.KeyChar);
}
public void MyKeyUp(object sender, KeyEventArgs e)
{
//LogWrite("KeyUp - " + e.KeyData.ToString());
}
private void LogWrite(string txt)
{
writeFile(txt);
}
private void writeFile(string s)
{
try
{
//Open the File
StreamWriter sw = new StreamWriter("C:\\Test1.txt",
true, Encoding.ASCII);
sw.Write(s);
//close the file
sw.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
finally
{
//exception supressed
}
}
}
}
** To leave the list, click on the immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=unsubscribe]
** If this link doesn't work then send a message to:
** program-l-request@xxxxxxxxxxxxx
** and in the Subject line type
** unsubscribe
** For other list commands such as vacation mode, click on the
** immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=faq]
** or send a message, to
** program-l-request@xxxxxxxxxxxxx with the Subject:- faq
** To leave the list, click on the immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=unsubscribe]
** If this link doesn't work then send a message to:
** program-l-request@xxxxxxxxxxxxx
** and in the Subject line type
** unsubscribe
** For other list commands such as vacation mode, click on the
** immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=faq]
** or send a message, to
** program-l-request@xxxxxxxxxxxxx with the Subject:- faq
- Follow-Ups:
- References:
Other related posts:
- » [program-l] C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
- » [program-l] Re: C#: creating a service that logs mouse and keyboard input
Hi all,
I am trying to write an aplication in c# that logs all keystrokes to a file. The application uses a global system hook. The program runs as expected when I run it as a Windows application. I have tried to convert the application to run as a service. This is not working. The application runs but the key logging does not happen. I could be doing something wrong when running it as a service. I will paste that code at the end of the message. As far as I can tell, no exceptions are thrown.
Jaws and een Narrator become sluggish when I run the service so I am wondering whether screen readers and the application are not getting along. I have tried tracing through the code but Visual Studio 2005 locks up when I reach the line installing the keyboard hook. (actHook.KeyDown += new KeyEventHandler(MyKeyDown);) Mind you, the task manager still shows Visual Studio as running. This does not happen when I run the application as a windows application. Note: I have used threading which has improved the performance of the app but I am missing something since the logging is not happening.
I have read http://www.albahari.com/threading/ for threading and several articles over the web while creating this application.
The code for creating the global hooks has been taken from http://www.codeproject.com/csharp/globalhook.asp I have created the windows service after referencing http://www.codeproject.com/csharp/WindowsService.asp. Note: I am using Visual studio .net (express) 2005.
Pranav
using System; using System.Diagnostics; using System.ServiceProcess; using System.IO; using System.Text; using System.Windows.Forms; using System.Threading; using gma.System.Windows;
namespace WindowsService
{
class WindowsService : ServiceBase
{
UserActivityHook actHook;
Thread t;
/// <summary>
/// Public Constructor for WindowsService.
/// - Put all of your Initialization code here.
/// </summary>
public WindowsService()
{
this.ServiceName = "keyLog";
this.EventLog.Source = "KeyLog";
this.EventLog.Log = "Application"; // These Flags set whether or not to handle that specific
// type of event. Set to true if you need it, false otherwise.
this.CanHandlePowerEvent = true;
this.CanHandleSessionChangeEvent = true;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.CanStop = true;if (!EventLog.SourceExists("My Windows Service"))
EventLog.CreateEventSource("My Windows Service", "Application");
}
/// <summary>
/// The Main Thread: This is where your Service is Run.
/// </summary>
static void Main()
{
ServiceBase.Run(new WindowsService());}
/// <summary>
/// Dispose of objects that need it here.
/// </summary>
/// <param name="disposing">Whether or not disposing is going
on.</param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
} /// <summary>
/// OnStart: Put startup code here
/// - Start threads, get inital data, etc.
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
base.OnStart(args);
actHook = new UserActivityHook(); // crate an instance
with global hooks
actHook.OnMouseActivity += new MouseEventHandler(MouseMoved);
actHook.KeyDown += new KeyEventHandler(MyKeyDown);
actHook.KeyPress += new KeyPressEventHandler(MyKeyPress);
actHook.KeyUp += new KeyEventHandler(MyKeyUp);
t = new Thread(delegate() { actHook.Start(); }); t.IsBackground = true; t.Start();
//actHook.Start(); }
/// <summary>
/// OnStop: Put your stop code here
/// - Stop threads, set final data, etc.
/// </summary>
protected override void OnStop()
{
base.OnStop();
actHook.Stop(); }
/// <summary>
/// OnPause: Put your pause code here
/// - Pause working threads, etc.
/// </summary>
protected override void OnPause()
{
actHook.Stop();
base.OnPause();
} /// <summary>
/// OnContinue: Put your continue code here
/// - Un-pause working threads, etc.
/// </summary>
protected override void OnContinue()
{
base.OnContinue();
actHook.Start();
} /// <summary>
/// OnShutdown(): Called when the System is shutting down
/// - Put code here when you need special handling
/// of code that deals with a system shutdown, such
/// as saving special data before shutdown.
/// </summary>
protected override void OnShutdown()
{
actHook.Stop();
LogWrite("shutdown detected");
base.OnShutdown();
}/// <summary>
/// OnCustomCommand(): If you need to send a command to your
/// service without the need for Remoting or Sockets, use
/// this method to do custom methods.
/// </summary>
/// <param name="command">Arbitrary Integer between 128 & 256</param>
protected override void OnCustomCommand(int command)
{
// A custom command can be sent to a service by using this method:
//# int command = 128; //Some Arbitrary number between 128 & 256
//# ServiceController sc = new ServiceController("NameOfService");
//# sc.ExecuteCommand(command);
base.OnCustomCommand(command);
}/// <summary>
/// OnPowerEvent(): Useful for detecting power status changes,
/// such as going into Suspend mode or Low Battery for laptops.
/// </summary>
/// <param name="powerStatus">The Power Broadcase Status
(BatteryLow, Suspend, etc.)</param>
protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
return base.OnPowerEvent(powerStatus);
}
/// <summary>
/// OnSessionChange(): To handle a change event from a
Terminal Server session.
/// Useful if you need to determine when a user logs in
remotely or logs off,
/// or when someone logs into the console.
/// </summary>
/// <param name="changeDescription"></param>
protected override void
OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
} public void MouseMoved(object sender, MouseEventArgs e)
{if (e.Clicks > 0) LogWrite("MouseButton - " + e.Button.ToString());
}
public void MyKeyDown(object sender, KeyEventArgs e) { LogWrite("{" + e.KeyData.ToString()+"}"); }
public void MyKeyPress(object sender, KeyPressEventArgs e)
{
LogWrite("KeyPress - " + e.KeyChar);
} public void MyKeyUp(object sender, KeyEventArgs e)
{
//LogWrite("KeyUp - " + e.KeyData.ToString());
} private void LogWrite(string txt)
{
writeFile(txt);
} private void writeFile(string s)
{ try
{
//Open the File
StreamWriter sw = new StreamWriter("C:\\Test1.txt",
true, Encoding.ASCII);sw.Write(s);
//close the file
sw.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
finally
{
//exception supressed
}
}} } ** To leave the list, click on the immediately-following link:- ** [mailto:program-l-request@xxxxxxxxxxxxx?subject=unsubscribe] ** If this link doesn't work then send a message to: ** program-l-request@xxxxxxxxxxxxx ** and in the Subject line type ** unsubscribe ** For other list commands such as vacation mode, click on the ** immediately-following link:- ** [mailto:program-l-request@xxxxxxxxxxxxx?subject=faq] ** or send a message, to ** program-l-request@xxxxxxxxxxxxx with the Subject:- faq