Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium


c++ , windows 2000 - Remotely get locally logged  username

Posted on 2007-10-03
Medium Priority
Last Modified: 2013-12-23

I'm currently trying to remotely find who is locally logged into windows 2000 workstations.  I have tried a couple of wmi methods: Reading the UserName property of the Win32_ComputerSystem object; and running the GetOwner() method of the Win32_Process object associated with the explorer.exe process.  Both of these methods work fine with windows XP, and on *some* of my windows 2000 workstations.

I am aware of using NetWkstaUserEnum to get logged on users, but that lists all logged on users, including any batch processes running, which is not what I want.

If someone knows of a good way to find just the locally logged on user, some reasoning on why the WMI methods would work on some windows 2000 workstations and not others, or a way to narrow NetWkstaUserEnum down to just the locally logged in user I would be very greatful.

Question by:mikerotch1000
  • 3
LVL 39

Expert Comment

ID: 20012994
>>>> If someone knows of a good way to find just the locally logged on user
If you write a little service which logs the locally logged on users at the server, you could compare that list with that of NetWkstaUserEnum to filter both the batch jobs and the ones already logged out. In case your clienst have a fixed IP address or your server acts as a DHCP server as well and you have access to the list of IP addresses, you might check the 'users' of the NetWkstaUserEnum whether they are available via TCP/IP. Another - maybe more simple way - is to have all batch login user's 'special' usernames which easily can be filtered.

>>>> why the WMI methods would work on some windows 2000 workstations
>>>> and not others,
I assume you already read the MSDN regarding that:
Windows 2000:  If you call this function on a domain controller that is running Active Directory, access is allowed or denied based on the access control list (ACL) for the securable object. The default ACL permits all authenticated users and members of the " Pre-Windows 2000 compatible access" group to view the information. By default, the "Pre-Windows 2000 compatible access" group includes Everyone as a member. This enables anonymous access to the information if the system allows anonymous access. If you call this function on a member server or workstation, all authenticated users can view the information. Anonymous access is also permitted if the RestrictAnonymous policy setting allows anonymous access.

Regards, Alex


Author Comment

ID: 20015037

Thank you for responding to my question.

I'd rather not rely on a service that dumps who just logged on to the server.  I might as well just read event 672's from the security logs on the dc (server).  This event reliably tells me when someone has logged onto a workstation at an ip address.

Now I might be wrong about this, but I don't think that NetWkstaUserEnum is part of WMI ... allthought it might utilize it.  I did find the Windows 2000 notes that you posted on the NetWkstaUserEnum page():

But I did not find it on the pages of any of the WMI objects / methods I'm using.
ExecMethod(): http://msdn2.microsoft.com/en-us/library/aa392103.aspx

GetOwner(): http://msdn2.microsoft.com/en-us/library/aa390460.aspx

Win32_ComputerSystem: http://msdn2.microsoft.com/en-us/library/aa394102.aspx

I did look into the RestrictAnonymous policy on a windows 2000 workstation that I can get the logged in username from and compared it to that of a windows 2000 workstation that I can not get the logged in username from.  They are identical - "None.  Rely on default permissions".

Now, I'm not sure what the default permissions are, so I suppose that those could be the culprit.  

The thing is that I'm connecting to this systems via WMI with a Domain Administrator account, so I'm not quite sure that the RestrictAnonymous policy would affect this.

If you have any thoughts on this WMI issue I would greatly appreciate them.

Thanks again

Author Comment

ID: 20024418

I just noticed that there is at least 1 windows XP machine that does not return a username from my wmi calls
LVL 41

Accepted Solution

graye earned 500 total points
ID: 20025084
Here is the technique that I use...  It's written in VB.Net, but you'll get the point

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"
            reg_hku = RegistryKey.OpenRemoteBaseKey(RegistryHive.Users, 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.GetSubKeyNames(), "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("CLIENTNAME", "").ToString = "Console" Then
                                    got_it = True
                                End If
                            End If
                        End If
                        If got_it Then
                            Exit For
                        End If
                    End If
            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(CurKey, 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)
                user = RemotePC & "\" & Left(UserName, name_len)
            End If
        Catch ex As Exception
            Return "Error"
        End Try

        Return user
    End Function
End Class

Author Comment

ID: 20052612
graye:  Thank you so much for posting.  your solution is excellent and did the trick for me

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
This is the first one of a series of articles I’ll be writing to address technical issues that are always referred to as network problems. The network boundaries have changed, therefore having an understanding of how each piece in the network  puzzl…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

564 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question