2

I am new to Active Directory.

I have a VBA Excel Add-In that should run if, and only if, the computer that it is running on is currently logged into the Active Directory, whether locally or through a VPN.

Knowing the domain name, how would I retrieve the user name for the currently logged in user?

Thanks!

Kuyenda
  • 4,529
  • 11
  • 46
  • 64
  • I already tried `Lib "advapi32.dll" Alias "GetUserNameA"` (http://stackoverflow.com/questions/677112/how-to-get-logged-in-users-name-in-access-vba) but it returns NULL when logged in via the VPN. – Kuyenda Oct 15 '09 at 21:00
  • My question was partly answered by http://stackoverflow.com/questions/1043436/how-do-i-get-the-current-user-identity-for-a-vpn-user-in-a-windows-forms-app. It appears that although I am logged onto the network via the VPN, I am not logged onto the Active Directory. So any method for for retrieving the AD username will fail. I also haven't found any way to query the username from the VPN client itself. – Kuyenda Mar 01 '10 at 19:15
  • Kuyenda, I know it's been a while. But please take a look at my answer. I believe it's the most appropriate, because I show that it is indeed possible to get the name for the currently logged in user. DragUserName() will get the user's actual Name, and fGetUserName() will get the logged user's Lan ID. – willmichels Jan 30 '13 at 21:18

4 Answers4

7

I know it's kinda late, but I went through hell last year to find the following code, that can return the username ("fGetUserName()") or the full name ("DragUserName()"). You don't even need to know the ad / dc address..

Hope this is helpful to anyone who consults this question.

Private Type USER_INFO_2
    usri2_name As Long
    usri2_password  As Long  ' Null, only settable
    usri2_password_age  As Long
    usri2_priv  As Long
    usri2_home_dir  As Long
    usri2_comment  As Long
    usri2_flags  As Long
    usri2_script_path  As Long
    usri2_auth_flags  As Long
    usri2_full_name As Long
    usri2_usr_comment  As Long
    usri2_parms  As Long
    usri2_workstations  As Long
    usri2_last_logon  As Long
    usri2_last_logoff  As Long
    usri2_acct_expires  As Long
    usri2_max_storage  As Long
    usri2_units_per_week  As Long
    usri2_logon_hours  As Long
    usri2_bad_pw_count  As Long
    usri2_num_logons  As Long
    usri2_logon_server  As Long
    usri2_country_code  As Long
    usri2_code_page  As Long
End Type

Private Declare Function apiNetGetDCName Lib "Netapi32.dll" Alias "NetGetDCName" (ByVal servername As Long, ByVal DomainName As Long, bufptr As Long) As Long

Private Declare Function apiNetAPIBufferFree Lib "Netapi32.dll" Alias "NetApiBufferFree" (ByVal buffer As Long) As Long

Private Declare Function apilstrlenW Lib "kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long

Private Declare Function apiNetUserGetInfo Lib "Netapi32.dll" Alias "NetUserGetInfo" (servername As Any, UserName As Any, ByVal level As Long, bufptr As Long) As Long

Private Declare Sub sapiCopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Declare Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Private Declare Function GetComputerName Lib "kernel32.dll" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Private strUserID As String

Private strUserName As String

Private strComputerName As String

Private Const MAXCOMMENTSZ = 256
Private Const NERR_SUCCESS = 0
Private Const ERROR_MORE_DATA = 234&
Private Const MAX_CHUNK = 25
Private Const ERROR_SUCCESS = 0&

Public Function fGetUserName() As String
 ' Returns the network login name
Dim lngLen As Long, lngRet As Long
Dim strUserName As String
    strUserName = String$(254, 0)
    lngLen = 255
    lngRet = apiGetUserName(strUserName, lngLen)
        If lngRet Then
            fGetUserName = Left$(strUserName, lngLen - 1)
        End If
End Function

Private Sub Class_Initialize()
On Error Resume Next
'Returns the network login name
Dim strTempUserID As String, strTempComputerName As String

'Create a buffer
strTempUserID = String(100, Chr$(0))
strTempComputerName = String(100, Chr$(0))

'Get user name
GetUserName strTempUserID, 100

'Get computer name
GetComputerName strTempComputerName, 100

'Strip the rest of the buffer
strTempUserID = Left$(strTempUserID, InStr(strTempUserID, Chr$(0)) - 1)
Let strUserID = LCase(strTempUserID)

strTempComputerName = Left$(strTempComputerName, InStr(strTempComputerName, Chr$(0)) - 1)
Let strComputerName = LCase(strTempComputerName)

Let strUserName = DragUserName(strUserID)

End Sub

Public Property Get UserID() As String
    UserID = strUserID
End Property

Public Property Get UserName() As String
    UserName = strUserName
End Property

Public Function DragUserName(Optional strUserName As String) As String
On Error GoTo ErrHandler
Dim pBuf As Long
Dim dwRec As Long
Dim pTmp As USER_INFO_2
Dim abytPDCName() As Byte
Dim abytUserName() As Byte
Dim lngRet As Long
Dim i As Long

    ' Unicode
    abytPDCName = fGetDCName() & vbNullChar
    If strUserName = "" Then strUserName = fGetUserName()
    abytUserName = strUserName & vbNullChar

    ' Level 2
    lngRet = apiNetUserGetInfo( _
                            abytPDCName(0), _
                            abytUserName(0), _
                            2, _
                            pBuf)
    If (lngRet = ERROR_SUCCESS) Then
        Call sapiCopyMem(pTmp, ByVal pBuf, Len(pTmp))
        DragUserName = fStrFromPtrW(pTmp.usri2_full_name)
    End If

    Call apiNetAPIBufferFree(pBuf)
ExitHere:
    Exit Function
ErrHandler:
    DragUserName = vbNullString
    Resume ExitHere
End Function

Public Property Get ComputerName() As String
    ComputerName = strComputerName
End Property

Private Sub Class_Terminate()
    strUserName = ""
    strComputerName = ""
End Sub

Public Function fGetDCName() As String
Dim pTmp As Long
Dim lngRet As Long
Dim abytBuf() As Byte

    lngRet = apiNetGetDCName(0, 0, pTmp)
    If lngRet = NERR_SUCCESS Then
        fGetDCName = fStrFromPtrW(pTmp)
    End If
    Call apiNetAPIBufferFree(pTmp)
End Function

Public Function fStrFromPtrW(pBuf As Long) As String
Dim lngLen As Long
Dim abytBuf() As Byte

    ' Get the length of the string at the memory location
    lngLen = apilstrlenW(pBuf) * 2
    ' if it's not a ZLS
    If lngLen Then
        ReDim abytBuf(lngLen)
        ' then copy the memory contents
        ' into a temp buffer
        Call sapiCopyMem( _
                abytBuf(0), _
                ByVal pBuf, _
                lngLen)
        ' return the buffer
        fStrFromPtrW = abytBuf
    End If
End Function
willmichels
  • 131
  • 1
  • 6
3

EDITED: If I understand your situation properly, then you might be going about this the wrong way.

When your app starts up, you could do a simple ping against a machine that the user would only be able to see if they were connected to your network, whether they log into the local network or if they are connected via the VPN.

If they already have access to your local network, it means they've already authenticated against whatever machanism, whether it's Active Directory or something else, and it means they are "currently logged in".

On a side note, Active Directory by itself doesn't know if someone is logged in. There's no way you can do something like:

ActiveDirectory.getIsThisUserLoggedIn("username");

Active Directory only acts as a mechanism for user metadata, security, and authentication.

Alex Beardsley
  • 20,988
  • 15
  • 52
  • 67
  • This is what I needed to know: "Active Directory by itself doesn't know if someone is logged in." Thanks Nalandial! – Kuyenda Mar 01 '10 at 19:07
0

Try this

MsgBox Environ("USERNAME")
Rubens Farias
  • 57,174
  • 8
  • 131
  • 162
  • That works if the user is logged in locally, but in some situations the user can log into the VPN using a different user name than their Windows user name. In those situations, I need the VPN user name. Thanks though! – Kuyenda Oct 15 '09 at 20:35
  • if your're executing your VBA code inside VPN, you'll get VPN username, not your local user. – Rubens Farias Oct 15 '09 at 20:54
  • Ruben, thanks for your suggestions. If I understand you correctly, you mean that I should store and run the add-in remotely. Unfortunately, I have to run it locally. – Kuyenda Oct 15 '09 at 21:21
  • Sorry, maybe I'm missing something; can you please elaborate on your VPN scenario? – Rubens Farias Oct 15 '09 at 21:29
  • Sure. I simply have a VPN client installed on my system. I connect the VPN using the username assigned to me, but that is not the same user name as my Windows username. Once the VPN is connected, all applications are able to connect to the relevant servers, otherwise connection is not possible. The VPN is not overriding the Windows authentication, although I know it is possible to do that. I need to retrieve the VPN username when the VPN is connected. – Kuyenda Oct 15 '09 at 21:44
  • Looks like the VPN is connected to the network but not the Active Directory. Someone else had a similar situation (http://stackoverflow.com/questions/1043436/how-do-i-get-the-current-user-identity-for-a-vpn-user-in-a-windows-forms-app). So, I guess I have to try to query the username from the VPN itself. – Kuyenda Oct 15 '09 at 23:42
  • Note that using any Environ variable is *NOT* secure. While unlikely a person can start the Command Prompt, change the environment variable and then run Excel from the command prompt. Excel will now happily use that value. – Tony Toews Oct 16 '09 at 23:21
  • This works well in my situation since our company uses the active directory login for both and in this situation, it's simply for record keeping, not security. – Rick Savoy Jul 06 '16 at 15:04
0

This function returns full name of logged user:

Function UserNameOffice() As String
    UserNameOffice = Application.UserName
End Function
pyOwner
  • 612
  • 5
  • 11
  • Unless I'm mistaken that just displays the username of the user who installed Excel and entered their name in the User box. May not necessarily be the logged in user. – Rick Henderson Nov 20 '18 at 19:47