JEFFCECCHINI
asked on
How to determine if XP Pro is logged off or locked by VB.Net scheduled task
Need to know in VB.Net (pref .Net 1.1) how determine if a WinXp Pro computer is locked or logged off.
I want to write an app that's run in the task scheduler nightly that determines if the computer is "logged off" and if so to reboot it.
There should be NO reboot (and it should email me) if the computer is locked at that time, which means that a user may have left applications/files open.
Thanks, Jeff
I want to write an app that's run in the task scheduler nightly that determines if the computer is "logged off" and if so to reboot it.
There should be NO reboot (and it should email me) if the computer is locked at that time, which means that a user may have left applications/files open.
Thanks, Jeff
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
This class uses Remote Procedure Calls (RPC) for performing it's functions across the network. So, there's the usual things that have to be right...
Services (RPC)
Firewall (which you've already looked at)
User Account/Permission (the account used must be in the Administrators group on both PCs)
Services (RPC)
Firewall (which you've already looked at)
User Account/Permission (the account used must be in the Administrators group on both PCs)
ASKER
Hi graye:
You have definitely earned the points on your original answer. I can award them now, however, if you can help me access this remotely, I will award an add'l 250. Do you want to go forward?
If so. the follow-up questions to your last answer:
"there's the ususal things that have to be right"
1. "Services (RPC)". I take this to mean that "Remote Procedure Call (RPC)" service must be running. It is "Automatic", however, RPC locator service is "Manual" and is not running. Is that important?
2. Firewall. Yes I have turned it off and tried with no luck.
3. User account I hadn't thought of. There is no domain, it's peer to peer (server 2003 O/S accessing a win Xp Pro on same LAN). I added in as a user into the XP Pro box the same user name w/ same password as what I'm logged into on the server, both administrators on their own machine, but still no luck
The server is trying to get the services form the XP Pro box.
FYI I just tried to shutdown the WinXp Pro box from the server using shutdown.exe (part of windows) and got the error:
"Access denied.(5)"
"Failed: 192.168.222.11"
Any ideas?
You have definitely earned the points on your original answer. I can award them now, however, if you can help me access this remotely, I will award an add'l 250. Do you want to go forward?
If so. the follow-up questions to your last answer:
"there's the ususal things that have to be right"
1. "Services (RPC)". I take this to mean that "Remote Procedure Call (RPC)" service must be running. It is "Automatic", however, RPC locator service is "Manual" and is not running. Is that important?
2. Firewall. Yes I have turned it off and tried with no luck.
3. User account I hadn't thought of. There is no domain, it's peer to peer (server 2003 O/S accessing a win Xp Pro on same LAN). I added in as a user into the XP Pro box the same user name w/ same password as what I'm logged into on the server, both administrators on their own machine, but still no luck
The server is trying to get the services form the XP Pro box.
FYI I just tried to shutdown the WinXp Pro box from the server using shutdown.exe (part of windows) and got the error:
"Access denied.(5)"
"Failed: 192.168.222.11"
Any ideas?
Hummmm.... that's a bit strange.
1) RPC... that looks normal
2) Did you make sure you turned off the firewall on both systems?
3) Typically, in a workgroup environment, all you need is to be using a user name and password that's common to both systems. That account must also be in the Administrators group on both systems. Note: The password can NOT be blank.
Here is an example of how to get the name of the user who is logged onto a remote PC. It uses Remote Registry Services (yet another thing to check for in the Services control panel applet)
Imports Microsoft.Win32
'
' Class to get the name of the remotely logged in user
'
Public Class GetUser
#Region "API Region"
'BOOL LookupAccountSid(
' LPCTSTR lpSystemName,
' PSID lpSid,
' LPTSTR lpName,
' LPDWORD cchName,
' LPTSTR lpReferencedDomainName,
' LPDWORD cchReferencedDomainName,
' PSID_NAME_USE peUse
');
Private Declare Auto Function LookupAccountSid Lib "advapi32.dll" ( _
ByVal lpSystemName As String, _
ByVal lpSid As IntPtr, _
ByVal lpName As String, _
ByRef cchName As Integer, _
ByVal lpReferenceDomainName As String, _
ByRef cchReferencedDomainName As Integer, _
ByRef peUse As Integer _
) As Boolean
'BOOL ConvertStringSidToSid(
' LPCTSTR StringSid,
' PSID* Sid
');
Private Declare Auto Function ConvertStringSidToSid Lib "advapi32.dll" ( _
ByVal StringSid As String, _
ByRef Sid As IntPtr _
) As Boolean
Private Const NAME_SIZE As Integer = 64
#End Region
Public Function GetRemoteUser(ByVal RemotePC As String) As String
Dim reg_hku, key, subkey As RegistryKey
Dim user, keyname, CurKey, UserName, DomainName As String
Dim name_len, domain_len, peUse As Integer
Dim got_it As Boolean
Dim Sid As IntPtr
CurKey = ""
user = "Error"
Try
reg_hku = RegistryKey.OpenRemoteBase Key(Regist ryHive.Use rs, RemotePC)
If Not IsNothing(reg_hku) Then
' Find the User key that has "Volatile Environment"... that's
' either the current user or the last user logged in.
got_it = False
For Each keyname In reg_hku.GetSubKeyNames()
key = reg_hku.OpenSubKey(keyname , False)
If Not IsNothing(key) Then
If Array.IndexOf(key.GetSubKe yNames(), "Volatile Environment") >= 0 Then
CurKey = keyname
' for WinXP's alternate login, we must check to
' see if the CLIENTNAME is "Console"
subkey = key.OpenSubKey("Volatile Environment")
If Not IsNothing(subkey) Then
If subkey.GetValue("CLIENTNAM E", "").ToString = "Console" Then
got_it = True
End If
subkey.Close()
End If
End If
key.Close()
If got_it Then
Exit For
End If
End If
Next
reg_hku.Close()
End If
' Nope, didn't find anything
If CurKey = "" Then
Return "Nobody"
End If
' In rare cases, the user's registry hive is still loaded. So
' to test if there is anybody currently logged on, we see if
' the remote PC has an explorer.exe process running
If Process.GetProcessesByName ("explorer ", RemotePC).Length = 0 Then
Return "Nobody"
End If
' Now let's get the logon name from the string version of the
' Sid (which is the registry key name)
If ConvertStringSidToSid(CurK ey, Sid) = False Then
Return "Error"
End If
name_len = NAME_SIZE
domain_len = NAME_SIZE
UserName = Space(name_len)
DomainName = Space(domain_len)
' look up the Account associated with that SID
If LookupAccountSid(RemotePC, Sid, UserName, name_len, DomainName, domain_len, peUse) = False Then
Return "Error"
End If
If domain_len > 0 Then
user = Left(DomainName, domain_len) & "\" & Left(UserName, name_len)
Else
user = RemotePC & "\" & Left(UserName, name_len)
End If
Catch ex As Exception
Return "Error"
End Try
Return user
End Function
End Class
1) RPC... that looks normal
2) Did you make sure you turned off the firewall on both systems?
3) Typically, in a workgroup environment, all you need is to be using a user name and password that's common to both systems. That account must also be in the Administrators group on both systems. Note: The password can NOT be blank.
Here is an example of how to get the name of the user who is logged onto a remote PC. It uses Remote Registry Services (yet another thing to check for in the Services control panel applet)
Imports Microsoft.Win32
'
' Class to get the name of the remotely logged in user
'
Public Class GetUser
#Region "API Region"
'BOOL LookupAccountSid(
' LPCTSTR lpSystemName,
' PSID lpSid,
' LPTSTR lpName,
' LPDWORD cchName,
' LPTSTR lpReferencedDomainName,
' LPDWORD cchReferencedDomainName,
' PSID_NAME_USE peUse
');
Private Declare Auto Function LookupAccountSid Lib "advapi32.dll" ( _
ByVal lpSystemName As String, _
ByVal lpSid As IntPtr, _
ByVal lpName As String, _
ByRef cchName As Integer, _
ByVal lpReferenceDomainName As String, _
ByRef cchReferencedDomainName As Integer, _
ByRef peUse As Integer _
) As Boolean
'BOOL ConvertStringSidToSid(
' LPCTSTR StringSid,
' PSID* Sid
');
Private Declare Auto Function ConvertStringSidToSid Lib "advapi32.dll" ( _
ByVal StringSid As String, _
ByRef Sid As IntPtr _
) As Boolean
Private Const NAME_SIZE As Integer = 64
#End Region
Public Function GetRemoteUser(ByVal RemotePC As String) As String
Dim reg_hku, key, subkey As RegistryKey
Dim user, keyname, CurKey, UserName, DomainName As String
Dim name_len, domain_len, peUse As Integer
Dim got_it As Boolean
Dim Sid As IntPtr
CurKey = ""
user = "Error"
Try
reg_hku = RegistryKey.OpenRemoteBase
If Not IsNothing(reg_hku) Then
' Find the User key that has "Volatile Environment"... that's
' either the current user or the last user logged in.
got_it = False
For Each keyname In reg_hku.GetSubKeyNames()
key = reg_hku.OpenSubKey(keyname
If Not IsNothing(key) Then
If Array.IndexOf(key.GetSubKe
CurKey = keyname
' for WinXP's alternate login, we must check to
' see if the CLIENTNAME is "Console"
subkey = key.OpenSubKey("Volatile Environment")
If Not IsNothing(subkey) Then
If subkey.GetValue("CLIENTNAM
got_it = True
End If
subkey.Close()
End If
End If
key.Close()
If got_it Then
Exit For
End If
End If
Next
reg_hku.Close()
End If
' Nope, didn't find anything
If CurKey = "" Then
Return "Nobody"
End If
' In rare cases, the user's registry hive is still loaded. So
' to test if there is anybody currently logged on, we see if
' the remote PC has an explorer.exe process running
If Process.GetProcessesByName
Return "Nobody"
End If
' Now let's get the logon name from the string version of the
' Sid (which is the registry key name)
If ConvertStringSidToSid(CurK
Return "Error"
End If
name_len = NAME_SIZE
domain_len = NAME_SIZE
UserName = Space(name_len)
DomainName = Space(domain_len)
' look up the Account associated with that SID
If LookupAccountSid(RemotePC,
Return "Error"
End If
If domain_len > 0 Then
user = Left(DomainName, domain_len) & "\" & Left(UserName, name_len)
Else
user = RemotePC & "\" & Left(UserName, name_len)
End If
Catch ex As Exception
Return "Error"
End Try
Return user
End Function
End Class
ASKER
By the way, I tried to obtain a list of processes remotely from another box (on the same LAN) using the overloaded method of Process.GetProcessesByName
I thought this might be a Win XP Pro firewall issue, so I turned it off, but still no luck, do you know what's preventing me from being able to obtain that?