[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.sdk

WindowsService: active user

Johannes

8/21/2003 10:21:00 PM

Hi!
I have WinXPro on my Computer and wanted to write a
Service with .net. This service shoud save the time a
user is logged on in a database. And I am able to create
and install a service, but if I tried to get the
CurrentUser (with e.g. SystemInformation.Username) it of
course sayd "LocalService" or "System". Because this is
the User the Thread runs in. But I want the user that is
logged on and the problem is, that in XP many users can
be logged on, but just one can actually be active. And I
found out that the Task-Manager has access to this
information, it can tell which users are logged on and
if they are active or "not connected". And I thought is
has to be anywhere in the registry (sam or
security\policy or so). So my question: where can i find
the user state?
Thanks
Johannes
9 Answers

Willy Denoyette

8/22/2003 12:13:00 PM

0

Johannes wrote:
|| Hi!
|| I have WinXPro on my Computer and wanted to write a
|| Service with .net. This service shoud save the time a
|| user is logged on in a database. And I am able to create
|| and install a service, but if I tried to get the
|| CurrentUser (with e.g. SystemInformation.Username) it of
|| course sayd "LocalService" or "System". Because this is
|| the User the Thread runs in. But I want the user that is
|| logged on and the problem is, that in XP many users can
|| be logged on, but just one can actually be active. And I
|| found out that the Task-Manager has access to this
|| information, it can tell which users are logged on and
|| if they are active or "not connected". And I thought is
|| has to be anywhere in the registry (sam or
|| security\policy or so). So my question: where can i find
|| the user state?
|| Thanks
|| Johannes

Easiest is to use the Management namespace classes (WMI wrappers) for this, following is a small sample:

using System;
using System.Management;
class tester {

private static ManagementObjectSearcher query;
public static void Main() {

ManagementScope msc = new ManagementScope("root\\cimv2");
string queryString = "select LogonId from win32_logonsession where logontype = 2";

query = new ManagementObjectSearcher(msc, new SelectQuery(queryString));

foreach( ManagementObject mo in query.Get()) {
Console.WriteLine( "ID ''{0}''", mo["LogonId"].ToString());
RelatedObjectQuery relatedQuery =
new RelatedObjectQuery
("associators of {Win32_LogonSession.LogonId=''" + mo["LogonId"]+ "''}");
relatedQuery.RelationshipClass = "win32_LoggedonUser";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(msc,relatedQuery);
foreach (ManagementObject mob in searcher.Get()) {
Console.WriteLine(mob["Caption"]);
Console.WriteLine("Domain {0}, Name {1}", mob["Domain"], mob["Name"]);

}
}

}
}


Johannes

8/23/2003 5:20:00 AM

0

the problem is that in winxp every local user can be
logged on. And you can get this information with your
programm,but i want to know who''s dektop is on the top or
if no user is active (maybe logged on) and you can just
see the logon screen! And i think windows has to know it,
so how can i get this information?
Johannes

Willy Denoyette

8/23/2003 10:30:00 AM

0

Johannes wrote:
|| the problem is that in winxp every local user can be
|| logged on. And you can get this information with your
|| programm,but i want to know who''s dektop is on the top or
|| if no user is active (maybe logged on) and you can just
|| see the logon screen! And i think windows has to know it,
|| so how can i get this information?
|| Johannes

Ok I see, you are talking about Terminal Server info (Fast user switching on XP).

Nothing built-in in the FCL, so Pinvoke is the message (note the same can be acomplished using WMI and the Management classes).
Here is a console sample using the WTS API''s (and PInvoke):
//Begin source
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
namespace WTSsessions
{
// Using Wtsapi32 (only available on Windows Server 2003 and XP)
// Get Session information using Terminal server API''s
// Requirements: see SDK docs
using HANDLE = System.IntPtr;
class Class1
{
static void Main(string[] args)
{
TerminalServer WTSinfo = new TerminalServer();
WTSinfo.GetSessionInfo();
}
}

class TerminalServer
{
[DllImport("wtsapi32", CharSet=CharSet.Auto, SetLastError=true), SuppressUnmanagedCodeSecurityAttribute]
static extern bool WTSEnumerateSessions (
HANDLE hServer, // Handle to a terminal server (from WTSOpenServer)
int Reserved, // dmust be 0
uint Version, // must be 1
ref IntPtr ppSessionInfo, // pointer to pointer to Processinfo
ref int pCount // no. of processes
);
[DllImport("wtsapi32", CharSet=CharSet.Auto, SetLastError=true), SuppressUnmanagedCodeSecurityAttribute]
static extern bool WTSQuerySessionInformation (
HANDLE hServer, // Handle to a terminal server (from WTSOpenServer)
uint sessionId, //
int WTSInfoClass, //
ref IntPtr ppBuffer, // pointer to pointer to returned info
ref int bCount // no. of bytes returned
);

[DllImport("wtsapi32", SetLastError=true), SuppressUnmanagedCodeSecurityAttribute]
static extern IntPtr WTSOpenServer (
string ServerName // Server name (NETBIOS)
);

[DllImport("wtsapi32", SetLastError=true), SuppressUnmanagedCodeSecurityAttribute]
static extern void WTSCloseServer (
HANDLE hServer // Handle obtained by WTSOpenServer
);

[DllImport("wtsapi32", SetLastError=true), SuppressUnmanagedCodeSecurityAttribute]
static extern void WTSFreeMemory (
IntPtr pMemory );

[StructLayout(LayoutKind.Sequential)]
struct WTSSessionInfo
{
internal uint SessionId;
[MarshalAs(UnmanagedType.LPTStr)] internal string pWinStationName;
internal uint State;
}
enum WTSConnectState
{
Active,
Connected,
ConnectQuery,
Shadow,
Disconnected,
Idle,
Listen,
Reset,
Down,
Init
}
enum WTSInfoClass
{
InitialProgram,
ApplicationName,
WorkingDirectory,
OEMId,
SessionId,
UserName,
WinStationName,
DomainName,
ConnectState,
ClientBuildNumber,
ClientName,
ClientDirectory,
ClientProductId,
ClientHardwareId,
ClientAddress,
ClientDisplay,
ClientProtocolType
}

public void GetSessionInfo()
{
HANDLE hServer = IntPtr.Zero;
IntPtr pInfo = IntPtr.Zero;
IntPtr pInfoSave = IntPtr.Zero;
WTSSessionInfo WTSsi; // Reference to ProcessInfo struct
IntPtr ppBuffer = IntPtr.Zero;
int bCount = 0;
int count = 0;
int iPtr = 0;
try
{
hServer = WTSOpenServer("scenic");
if(hServer == IntPtr.Zero)
Console.WriteLine(Marshal.GetLastWin32Error());
if (WTSEnumerateSessions(hServer, 0, 1, ref pInfo, ref count))
{
pInfoSave = pInfo;
Console.WriteLine("Number of sessions :{0}", count);
for(int n = 0; n < count; n++)
{
WTSsi = (WTSSessionInfo) Marshal.PtrToStructure(pInfo, typeof(WTSSessionInfo) );
iPtr = (int)(pInfo) + Marshal.SizeOf(WTSsi);
pInfo = (IntPtr)(iPtr);
Console.WriteLine(WTSsi.SessionId + "\t" + WTSsi.pWinStationName + "\t" + (WTSConnectState)WTSsi.State );
if(WTSQuerySessionInformation(hServer, WTSsi.SessionId, (int)WTSInfoClass.UserName, ref ppBuffer, ref bCount))
Console.WriteLine("User: {0}", Marshal.PtrToStringAuto(ppBuffer));
if(WTSQuerySessionInformation(hServer, WTSsi.SessionId, (int)WTSInfoClass.DomainName, ref ppBuffer, ref bCount))
Console.WriteLine("Domain: {0}", Marshal.PtrToStringAuto(ppBuffer));
if(WTSQuerySessionInformation(hServer, WTSsi.SessionId, (int)WTSInfoClass.WinStationName, ref ppBuffer, ref bCount))
Console.WriteLine("Windowstation: {0}",Marshal.PtrToStringAuto(ppBuffer));
}
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Free memory used
WTSFreeMemory(pInfoSave);
// Close server handle
WTSCloseServer(hServer);
}
}
}
}
// End source

Willy.


Willy Denoyette

8/23/2003 11:05:00 AM

0

Willy Denoyette [MVP] wrote:

Note WTSOpenServer takes the server name as argument (here "scenic"),
|| hServer = WTSOpenServer("scenic");
|| if(hServer == IntPtr.Zero)

if you run this on a local machine you don''t have to call this API, instead call WTSEnumerateSessions passing a null handle , like
this.

if (WTSEnumerateSessions(IntPtr.Zero, 0, 1, ref pInfo, ref count))
{


Willy.


Johannes

8/23/2003 8:46:00 PM

0

Thanks you so much!
Thanks for spending your time without getting something!
But let me ask you one thing: Where did you find this?
How do you know this?
Thanks
Johannes

Willy Denoyette

8/23/2003 9:08:00 PM

0

Johannes wrote:
|| Thanks you so much!
|| Thanks for spending your time without getting something!
|| But let me ask you one thing: Where did you find this?
|| How do you know this?
|| Thanks
|| Johannes

Well, I know Taskmgr.exe use the WTS API''s when running on a "fast task switching" enabled Windows XP box.
For detailed info about this API set, refer to the Platform SDK documentation or the MSDN Library (Platform SDK: Terminal Services).
Once you have the API''s it''s easy to define the PInvoke declarations, and use them from any managed language.

Willy.


Johannes

8/24/2003 9:53:00 PM

0

I have another question: When on user is active and i
have a timer running that gives me every second the
username of the active user, it doesn''t change when i
change to the loggon screen. It is still the same user
name, but if i select another user it changes of course,
so how can i get the information wether the logon screen
is active or not?
Thanks

Johannes

8/25/2003 7:13:00 AM

0

I found a function that can be a solution:


BOOL WINAPI
WTSRegisterSessionNotification(
HWND hWnd, // Window handle
DWORD dwFlags // Flags
);


I tried to include it with:

[DllImport
("wtsapi32",CharSet=CharSet.Auto,SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool
WTSRegisterSessionNotification(
HWND hWnd,
DWORD dwFlags
);


But i don''t know how to recieve these messages with c#
and a service. I don''t have a HWnd and he doesn''t even
know the HWND handle. I tought maybe it works with:

using HWND =System.IntPtr;
using DWORD=System.IntPtr;

And the value for the dwFlags should be:
NOTIFY_FOR_ALL_SESSIONS
But he doesn''t know it either.

Here my question:
1.How and where can I learn that stuff, because in th
msdn is not much about getting it work there are just
function and articles
2. Could you please help me?
Thanks
Johannes

Willy Denoyette

8/25/2003 9:51:00 AM

0

Johannes wrote:
|| I found a function that can be a solution:
||
||
|| BOOL WINAPI
|| WTSRegisterSessionNotification(
|| HWND hWnd, // Window handle
|| DWORD dwFlags // Flags
|| );
||
||
|| I tried to include it with:
||
|| [DllImport
|| ("wtsapi32",CharSet=CharSet.Auto,SetLastError=true),
|| SuppressUnmanagedCodeSecurityAttribute]
|| static extern bool
|| WTSRegisterSessionNotification(
|| HWND hWnd,
|| DWORD dwFlags
|| );
||
||
|| But i don''t know how to recieve these messages with c#
|| and a service. I don''t have a HWnd and he doesn''t even
|| know the HWND handle. I tought maybe it works with:
||
|| using HWND =System.IntPtr;
|| using DWORD=System.IntPtr;
||

Ok for a HWND you can use System.IntPtr, but a DWORD is simply a System.Int32 (or int in C#).


|| And the value for the dwFlags should be:
|| NOTIFY_FOR_ALL_SESSIONS
|| But he doesn''t know it either.
||
|| Here my question:
|| 1.How and where can I learn that stuff, because in th
|| msdn is not much about getting it work there are just
|| function and articles

Check the API descriptions on MSDN, and install (if you didn''t already) the latest Platform SDK (downloadable from Microsoft), if
looking for samples or problem descriptions, check the Knowledge base.
When looking for PInvoke stuff, check the .NET SDK docs in MSDN
However, take care when using these functions from managed code, because:
- If a large number of Win32 are used within a small application, you probably have chosen the wrong language/platform for the job,
here I mean that you should use C++ (or ME C++). The Platform SDK and Win32 API set is written with C (C++) as a target, Pinvoke is
only a bridge between the managed and unmanaged worlds, but it requires you to learn both sides to be successful.
- They can be covered directly or indirectly by the framework classes, especially most of the ''management'' style API''s are covered
by the System.Management namespace classes (WMI wrappers).

|| 2. Could you please help me?
|| Thanks
|| Johannes