473,570 Members | 2,855 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Getting logged in user from a service?

I am writing a service that monitors when a particular app is started.
Works, but I need to get the user who is currently logged in, and of course
Environment.Use rName returns the service logon (NT_AUTHORITY\S YSTEM).

I understand that when the service starts, no user may be logged in, but
that's ok, as the app I am monitoring can only be run by a logged in user.
Do I need to use WMI to get the user context of Explorer.exe or is there a
neater way?

James.

Jun 4 '07 #1
33 11825
James,

I'm assuming you are using the Process class or something similar? If
so, you can get the handle to the process through the Handle property.

Once you have that, you can call OpenProcessToke n (through the P/Invoke
layer) to open the process token for reading. Once you have that, you can
then call the GetTokenInforma tion function (again through the P/Invoke
layer) to get the SID of the user that began the process.

Finally, you can call the LookupAccountSi d API function using the
pointer to the SID to get the domain name, user name, etc, etc.

Make sure you call CloseHandle on the token you get from the call to
GetTokenInforma tion.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"JamesB" <ja***@somewher e.com.net.com.n etwrote in message
news:46******** *************** @news.zen.co.uk ...
>I am writing a service that monitors when a particular app is started.
Works, but I need to get the user who is currently logged in, and of
course Environment.Use rName returns the service logon
(NT_AUTHORITY\S YSTEM).

I understand that when the service starts, no user may be logged in, but
that's ok, as the app I am monitoring can only be run by a logged in user.
Do I need to use WMI to get the user context of Explorer.exe or is there a
neater way?

James.

Jun 4 '07 #2
"JamesB" <ja***@somewher e.com.net.com.n etwrote in message
news:46******** *************** @news.zen.co.uk ...
>I am writing a service that monitors when a particular app is started.
Works, but I need to get the user who is currently logged in, and of
course Environment.Use rName returns the service logon
(NT_AUTHORITY\S YSTEM).

I understand that when the service starts, no user may be logged in, but
that's ok, as the app I am monitoring can only be run by a logged in user.
Do I need to use WMI to get the user context of Explorer.exe or is there a
neater way?

James.

The easiest is to use System.Manageme nt and WMI's "Win32_ProcessS tartTrace"
class.
Here is how:

using System.Manageme nt;
using System.Security .Principal;
....
void WatchProcessSta rt(string procName)
{
WqlEventQuery q = new WqlEventQuery( );
q.EventClassNam e = "Win32_ProcessS tartTrace";
q.Condition = "ProcessNam e = '" + procName + "'"; // Put the process
name you want to watch for here...
using(Managemen tEventWatcher w = new ManagementEvent Watcher(q)){
w.EventArrived += new
EventArrivedEve ntHandler(Proce ssStartEventArr ived);
w.Start();
// BLOCK this thread, wait for an event to stop the handler and
return...
...
w.Stop();
}
}
static void ProcessStartEve ntArrived(objec t sender, EventArrivedEve ntArgs
e) {
foreach(Propert yData pd in e.NewEvent.Prop erties) {
string userAccount =
GetUserAccountF romSid(((byte[])e.NewEvent.Pro perties["Sid"].Value)));
// do something with "userAccoun t" ..
}
}
static string GetUserAccountF romSid(byte[] sid)
{
SecurityIdentif ier si = new SecurityIdentif ier(sid, 0);
NTAccount acc = (NTAccount)si.T ranslate(typeof (NTAccount));
return acc.Value;
}
Willy.

Jun 4 '07 #3

"JamesB" <ja***@somewher e.com.net.com.n etwrote in message
news:46******** *************** @news.zen.co.uk ...
>I am writing a service that monitors when a particular app is started.
Works, but I need to get the user who is currently logged in, and of
course
You used the phrase "the user", so this is required reading:
http://blogs.msdn.com/oldnewthing/ar...22/712677.aspx

Make sure you've thought about the questions Raymond asks, then use one of
the solutions already provided by Willy or Nicholas.
Jun 5 '07 #4

"Ben Voigt [C++ MVP]" <rb*@nospam.nos pamwrote in message
news:%2******** ********@TK2MSF TNGP02.phx.gbl. ..
>
"JamesB" <ja***@somewher e.com.net.com.n etwrote in message
news:46******** *************** @news.zen.co.uk ...
>>I am writing a service that monitors when a particular app is started.
Works, but I need to get the user who is currently logged in, and of
course

You used the phrase "the user", so this is required reading:
http://blogs.msdn.com/oldnewthing/ar...22/712677.aspx

Make sure you've thought about the questions Raymond asks, then use one of
the solutions already provided by Willy or Nicholas.
Valid points - it's actually conceivable that users would be running the
monitored application on a terminal server, so I guess when I said "user" I
am indeed meaning the user who has started the monitored application, not
just whoever is logged in on the console!

Jun 5 '07 #5

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote in
message news:u%******** ********@TK2MSF TNGP03.phx.gbl. ..
James,

I'm assuming you are using the Process class or something similar? If
so, you can get the handle to the process through the Handle property.

Once you have that, you can call OpenProcessToke n (through the P/Invoke
layer) to open the process token for reading. Once you have that, you can
then call the GetTokenInforma tion function (again through the P/Invoke
layer) to get the SID of the user that began the process.

Finally, you can call the LookupAccountSi d API function using the
pointer to the SID to get the domain name, user name, etc, etc.

Make sure you call CloseHandle on the token you get from the call to
GetTokenInforma tion.

Hope this helps.
The "process" I have is Win32_Process (from following another example), so
my code is as below, however my token is always zero.
The "Handle" property on the process object is a string, hence the
conversion to Intptr to pass to the OpenProcessToke n command, so perhaps
it's not the same thing?
The process object I have also has GetOwner() and GetOwnerSid() methods,
which would be ideal, however these always seem to return null! The process
object must be correct in a sense though, as the start and stop events where
I pass proc.ProcessID are indeed returning the correct PID as shown in Task
Manager.
James.

private void OnEventArrived( object sender,
System.Manageme nt.EventArrived EventArgs e)
{
try
{
string eventName = e.NewEvent.Clas sPath.ClassName ;

//Create process obj
WMI.Win32.Proce ss proc = new
WMI.Win32.Proce ss(e.NewEvent["TargetInstance "] as ManagementBaseO bject);

//Get handle...
int ph = Convert.ToInt32 (proc.Handle);
IntPtr pHandle = new IntPtr(ph);
IntPtr token = IntPtr.Zero;

//get processtoken
try
{
if (OpenProcessTok en(pHandle, TOKEN_ACCESS.TO KEN_QUERY,
out token) == 0)
{
//throw new ApplicationExce ption("Can't open process
token for: " + process.Process Name);
}
CloseHandle(tok en);
}
catch (Exception ex)
{
System.Diagnost ics.Debug.Write Line(ex.Message );
}

String userAccount = "";

if (eventName.Comp areTo("__Instan ceCreationEvent ")==0)
{
// Started
if (Started!=null)
Started(this, e, (Int16)proc.Pro cessId,
userAccount);

}
else if (eventName.Comp areTo("__Instan ceDeletionEvent ")==0)
{
// Terminated
if (Terminated!=nu ll)
Terminated(this , e, (Int16)proc.Pro cessId,
userAccount );

}
}
catch (Exception ex)
{
System.Diagnost ics.Debug.Write Line(ex.Message );
}
}

Jun 5 '07 #6
"JamesB" <ja***@somewher e.com.net.com.n etwrote in message
news:46******** *************** @news.zen.co.uk ...
>
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c omwrote
in message news:u%******** ********@TK2MSF TNGP03.phx.gbl. ..
>James,

I'm assuming you are using the Process class or something similar? If
so, you can get the handle to the process through the Handle property.

Once you have that, you can call OpenProcessToke n (through the
P/Invoke layer) to open the process token for reading. Once you have
that, you can then call the GetTokenInforma tion function (again through
the P/Invoke layer) to get the SID of the user that began the process.

Finally, you can call the LookupAccountSi d API function using the
pointer to the SID to get the domain name, user name, etc, etc.

Make sure you call CloseHandle on the token you get from the call to
GetTokenInform ation.

Hope this helps.
The "process" I have is Win32_Process (from following another example), so
my code is as below, however my token is always zero.
The "Handle" property on the process object is a string, hence the
conversion to Intptr to pass to the OpenProcessToke n command, so perhaps
it's not the same thing?
The process object I have also has GetOwner() and GetOwnerSid() methods,
which would be ideal, however these always seem to return null! The
process object must be correct in a sense though, as the start and stop
events where I pass proc.ProcessID are indeed returning the correct PID as
shown in Task Manager.
James.

private void OnEventArrived( object sender,
System.Manageme nt.EventArrived EventArgs e)
{
try
{
string eventName = e.NewEvent.Clas sPath.ClassName ;

//Create process obj
WMI.Win32.Proce ss proc = new
WMI.Win32.Proce ss(e.NewEvent["TargetInstance "] as ManagementBaseO bject);

//Get handle...
int ph = Convert.ToInt32 (proc.Handle);
IntPtr pHandle = new IntPtr(ph);
IntPtr token = IntPtr.Zero;

//get processtoken
try
{
if (OpenProcessTok en(pHandle, TOKEN_ACCESS.TO KEN_QUERY,
out token) == 0)
{
//throw new ApplicationExce ption("Can't open
process token for: " + process.Process Name);
}
CloseHandle(tok en);
}
catch (Exception ex)
{
System.Diagnost ics.Debug.Write Line(ex.Message );
}

String userAccount = "";

if (eventName.Comp areTo("__Instan ceCreationEvent ")==0)
{
// Started
if (Started!=null)
Started(this, e, (Int16)proc.Pro cessId,
userAccount);

}
else if (eventName.Comp areTo("__Instan ceDeletionEvent ")==0)
{
// Terminated
if (Terminated!=nu ll)
Terminated(this , e, (Int16)proc.Pro cessId,
userAccount );

}
}
catch (Exception ex)
{
System.Diagnost ics.Debug.Write Line(ex.Message );
}
}


You should use "Win32_ProcessS tartTrace" for this (supposing you are running
XP or higher), take a look at my other reply in this thread for details.

Willy.

Jun 5 '07 #7

"Willy Denoyette [MVP]" <wi************ *@telenet.bewro te in message
news:2C******** *************** ***********@mic rosoft.com...
You should use "Win32_ProcessS tartTrace" for this (supposing you are
running XP or higher), take a look at my other reply in this thread for
details.

Willy.
Your example looked like it would block when the monitored app ran (until it
stopped?) - is that right? Not tried it yet.
Plus, manu users are still on W2k so if the Win32_ProcessSt artTrace option
is XP or above, it may not be suitable.
Thanks though!

Jun 5 '07 #8
"JamesB" <ja***@somewher e.com.net.com.n etwrote in message
news:46******** *************** @news.zen.co.uk ...
>
"Willy Denoyette [MVP]" <wi************ *@telenet.bewro te in message
news:2C******** *************** ***********@mic rosoft.com...
>You should use "Win32_ProcessS tartTrace" for this (supposing you are
running XP or higher), take a look at my other reply in this thread for
details.

Willy.

Your example looked like it would block when the monitored app ran (until
it stopped?) - is that right? Not tried it yet.
Not at all, in the sample I need to block the thread that owns the
ManagementEvent Watcher object, this is required to keep the object alive as
long as you need to watch for events. Events from the trace provider keep
arriving on a worker thread from the pool.

Plus, manu users are still on W2k so if the Win32_ProcessSt artTrace option
is XP or above, it may not be suitable.
True, but this means that in this case you are "watching" for instance
events on the Win_Process class, this implies polling with the inherent risk
to miss events.

Anyway, when you got the PID of the process, you can get the owner by
calling the "GetOwner" method on the Win32_process class instance.
Here is how...
static string GetOwner(int Pid)
{
string owner = null;
SelectQuery selectQuery = new SelectQuery(Str ing.Format("Sel ect *
from Win32_Process where ProcessId={0}", Pid));
Console.WriteLi ne(selectQuery. QueryString);
using (ManagementObje ctSearcher searcher =
new ManagementObjec tSearcher(selec tQuery))
{
foreach (ManagementObje ct proc in searcher.Get())
{
Console.WriteLi ne(proc["Name"].ToString());
string[] s = new String[2];
proc.InvokeMeth od("GetOwner", (object[])s);
if (String.IsNullO rEmpty(s[0]))
owner = "NA";
else
owner = s[1] + "\\" + s[0];
}
}
return owner;
}

However, keep in mind that you wont get anything back if the process has
already terminated at the moment you call this function.
This can happen when short living processes are getting traced.
Willy.

Jun 5 '07 #9
Your example looked like it would block when the monitored app ran (until
it stopped?) - is that right? Not tried it yet.
Plus, manu users are still on W2k so if the Win32_ProcessSt artTrace option
is XP or above, it may not be suitable.
Thanks though!
Whatever method you choose, you'll still have to factor in what happens if
the service is stopped and then re-started (given that the app you're
monitoring may already be running at this point - or rather this is usually
an issue unless your app is dependent on the service in some way). I don't
know what WMI classes you should rely on off-hand to assist in this area (to
enumerate and locate running processes) since I normally rely on the the
WinAPI itself. In this regard Nicholas' technique is more mainstream (really
the de facto way of doing things) though WMI is normally easier (and worth
considering on those merits though I'd personally stick with the WinAPI
because it is more mainstream).
Jun 5 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2940
by: Saradhi | last post by:
Hi All, Can any one tell me the way to check whether a given user name is a member of domain users or not. I do not know the domain name as well. I should retreive from the logged in user, in which user account my appliation is running. If the system is not a part of domain controller then i should check for the user name in the current...
1
2559
by: amwi | last post by:
I have tried to find a solution on this problem "everywhere" without any luck. I am writing a service to track the time that the current logged on interactive user is using the computer. Perhaps one of you experts out there can point me in the right direction? Thank you for any help!
8
9995
by: Rod | last post by:
I have been working with ASP.NET 1.1 for quite a while now. For some reason, opening some ASP.NET applications we wrote is producing the following error message: "The Web server reported the following error when attempting to create or open the Web project located at the following URL: 'http://localhost/WebApplication1'. 'HTTP/1.1 500...
2
4848
by: Jim Covington | last post by:
I am writing a program that needs certain information from a pc on a network. I have it written and it is a vb.net service. I need the logged in user name. The app now returns a user "SYSTEM" because it is a service. How does one get the logged in user? Also, I need the IPAddress, THe Service Pack Level of the OS, and other system...
16
3411
by: Jm | last post by:
Hi All Is it possible to determine who is logged onto a machine from inside a service using code in vb.net ? I have found some code that seems to work under vb6, but doesnt under .NET ? Any help is greatly appreciated Thanks
4
2110
by: GTi | last post by:
Is there any way I can find out if there is any user logged on the desktop from a service?
4
8297
by: JamesB | last post by:
A week or two ago I posted queries about retrieving user details about a certain process and it all worked fine in the end, the service happily reported when the required application was started/stopped and everyone was happy. A new problem has come to light though, that when someone turns on their PC, my service isn't starting. Looking in...
0
2109
by: thephatp | last post by:
Is there any possible way to get the currently logged in (active) user from within a service? I need the service to start at runtime. I need to capture log on / log off / switch user events. I haven't gotten to that yet, but it IS possible from within a windows service, correct? I figured I'd ask because of my current problem. Line of...
0
621
by: =?Utf-8?B?UmF2aQ==?= | last post by:
Hi, I have WCF service and integrated with STS (WS-Federation). The Service exposes 5 endpoints Win, UNT and Federated Windows, Federated UNT and Mex endpoint. My STS Service exposes 3 endpoints WIN, UNT and Mex. I am getting error when I sent a request from a client to WCF Service Fed-Win/ Fed-Unt endpoints. But it is passing for the...
0
7950
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7702
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8000
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6332
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5247
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3671
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2133
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1238
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
974
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.