There are different ways to retrieve the "currently logged on users", it's
however not that easy to get what you call "the currently active
interactive
user". The reason for this is that you can have multiple "active
interactive
logon sessions" in Windows.
The most reliable way to get at this info is by using System.Management to
query the security eventlog, most Windows versions do write a
"Logon/Logoff
record" to the security log (policy dependent) whenever an account logs on
to the system or domain. In order to trace the Logon/Logoff activity, one
could use System.Management and ManagementEventWatcher to watch the
Logon/Logoff as they get written to the eventlog.
When running Vista, one can use the latest
System.Diagnostics.Eventing.Reader EventLogQuery class to get at the same
info as the above method.
Willy.- Hide quoted text -
- Show quoted text -
Thanks for the responses, everyone. This has been really insightful.
Not encouraging, but insightful.
So, Willy, when you say "policy dependent", what type of scenario are
you talking about? Is this typically in a corporate environment,
where an IT group is pushing out policies? Or is this a likely/
unlikely/etc. scenario for the average user at home? And I'm assuming
there is not other way to do this? I figured it was a long shot, but
I was really hoping a I could grab an event of some sort that is fired
in windows that I could catch. Then again, I know so little about
Windows Services vs. Applications--I don't even know if you can use
events (and delegates) in a Windows Service. Is that possible?
Thanks!
Chad
Chad,
When say policy I mean "local", domain imposed "group
policy" management and default OS behavior. For instance it's possible that
logging is prevented by
Group Policy managent, also local policies may prevent this, although these
can easily be changed by a local admin.
So, first thing you need to know is your environment, that is the OS
version(s), the
Framework version and kind policy management , after that you have to
inspect your
Security eventlog to see whether logon/logoff events are written. If there
aren't any Logon/Logoff messages written, you'll have to change the policy
(may depend on the OS version).
Only after you see the logon/logoff events in the Security log, you can
start
coding, keep in mind that different OS versions may require some different
techniques, you'll have to code accordingly.
One way to watch for Logon/Logon events, which works on all OSses (XP and
up), is by using System.Management
(basically WMI wrappers) to listen for the Logon/Logoff events when they get
written into the security log.
In your service process, you'll have to spawn a thread to run the Eventlog
"watcher", you may let this thread run until the service stops.
Following snip illustrates the process, I hope it helps to get you
started...
using System.Management;
....
// Thread procedure, start this thread from within OnStart of from
your own service thread procedure.
// Initialize an Eventlog event watcher to look for Security events
with EventIdentifier = 528 (Logon events)
// Note that 528 is valid for W2K, XP, W2K3, this value is not valid
for Vista and higher!
public void WatchLogonEvent(object stateObject)
{
AutoResetEvent stopWatcher = stateObject as AutoResetEvent;
WqlEventQuery q = new WqlEventQuery();
q.EventClassName = "__InstanceCreationEvent";
q.WithinInterval = new TimeSpan(0, 0, 3);
q.Condition = @"TargetInstance ISA 'Win32_NtLogEvent' and
TargetInstance.LogFile='Security' and TargetInstance.EventIdentifier=528";
try
{
using(ManagementEventWatcher watcher = new
ManagementEventWatcher(q))
{
watcher.EventArrived += new
EventArrivedEventHandler(LogonEventArrived);
watcher.Start();
// wait for a stop event
stopWatcher.WaitOne();
watcher.Stop();
}
}
catch(Exception e)
{
// log the event and stop the thread in case of failure, ...
here dump the exception to the debugger
Debug.WriteLine(e);
}
}
// Handle the event, this sample eventhandler dumps all properties
to the debugger
static void LogonEventArrived(object sender, EventArrivedEventArgs
e)
{
foreach(PropertyData pd in e.NewEvent.Properties)
{
ManagementBaseObject mbo = null;
if(( mbo = pd.Value as ManagementBaseObject) != null)
{
foreach(PropertyData prop in mbo.Properties)
{
string eventMessage = string.Format("{0} - {1}",
prop.Name, prop.Value);
// Parse the "InsertionString" property ... to
filter what you need
// For demo purposes dump the string to the debugger
Debug.WriteLine(eventMessage);
}
}
}
}
Check MSDN for details on the Win32_NtLogEvent properties.
Willy.