Solved

Get username alias from NT

Posted on 2000-04-27
27
548 Views
Last Modified: 2008-03-17
Folks,

I'm using Access 97 on NT 4 workstation (& server) and I want to be able to capture the username of the person currently logged on.

Environ$("UserName") will return the system login name (in my case "p0034789") but is there a way of capturing the 'friendlier' username (ie. "Andrew James Sharp"). I'm guessing there is an environment variable containing this information as my system says "Good morning, Andrew James Sharp" whenever I log in.

Any suggestions?
0
Comment
Question by:dramaqueen
  • 13
  • 11
  • 2
  • +1
27 Comments
 
LVL 10

Expert Comment

by:paasky
ID: 2755160
Hello dramaqueen,

You can view all the enviroment variables using console and typing SET. Unfortunately I didn't see variable containing full username information. I also tried to search the registry, that I could somehow use it to return full name - no match. Seems that full user information is encrypted into password file and might not be available... but I'm going to investigate more.

Regards,
Paasky
0
 

Author Comment

by:dramaqueen
ID: 2755216
Thanks, Paasky.

Woh! I'd thought this would be a fairly easy one. If it looks like being too horrendous I'll just use CASE or some kind of look up conversion, since I know which people will be using the system.

I just thought it would be more elegant to take it direct from the environment...

A.
0
 
LVL 10

Expert Comment

by:paasky
ID: 2755252
Okay, I did some research (used first Quick View program to view advapi32.dll and netapi32.dll), then I searched EE windows topic area and found this thread (cost me 10 points but what the heck, I might have use for this too):

--------------------------------------------------------------------------------
 10 points have been deducted from your account.
 
From: jnearing  Title: "return logged in user's full name"  Points: 10  
Answer Grade: A  Date: Wednesday, June 16 1999 - 10:02PM EEST    
We have Windows NT 4.0 servers and Windows 95 (and 98) workstations using domain logins.
I need to be able to obtain the logged in user's full name.
The login ID is generally the person's first name and last initial, which is easy enough to get, but I need their first and last name which is specified in the full name field.   The programming environment is Visual Basic 6.0 Enterprise Edition.

thanks


 
Accepted Answer  
From: livni
 Date: Wednesday, June 16 1999 - 10:30PM EEST    


Text below...

Question History  
Comment  
From: livni
 Date: Wednesday, June 16 1999 - 10:30PM EEST  
NetUserGetInfo is the function you are looking for.

If you need more details I can give you.


 
Accepted Answer  
From: livni
 Date: Wednesday, June 16 1999 - 10:30PM EEST  
NetUserGetInfo is the function you are looking for.

If you need more details I can give you.



 
Comment  
From: jnearing
 Date: Thursday, June 17 1999 - 06:45PM EEST  
Thanks, I forgot about that function.

--------------------------------------------------------------------------------

So you need to use NetUserGetInfo API to get the required information. Let me know if you need more assistance.

Regards,
paasky
0
 
LVL 10

Expert Comment

by:paasky
ID: 2755278
Here's the link which saves you for re-inventing the wheel:

http://www.vbsquare.com/articles/ntvb/index2.html

Hope this helps,
Paasky
0
 

Author Comment

by:dramaqueen
ID: 2755437
Adjusted points from 50 to 150
0
 

Author Comment

by:dramaqueen
ID: 2755438
Aaaaah! <Screams with fright!>

Erm... how do I extract a string from this function? I don't think my VB is up to Unicode buffers and so forth.

A.
0
 

Author Comment

by:dramaqueen
ID: 2755643
I found this - I'm trying to suss out whether I can simplify it down to a function which is simply

GetCurrUserFullName() as String

A.
http://www.mvps.org/access/api/api0058.htm

0
 
LVL 1

Expert Comment

by:tkuppinen
ID: 2755703
This has worked for me in VB so it should work in Access.  I can't remember from where I got the code so I can't give proper credit, sorry.

--Place this declaration in a module

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

--Place this function in the same module

Public Function returnUser() As String

Dim username As String, retval As Long

' receives name of the user

Dim slength As Long  ' length of the stringDim retval As Long  ' return value
' Create room in the buffer to receive the returned string.

username = Space(255)  ' room for 255 characters

slength = 255  ' initialize the size of the string

' Get the user's name and display it.
retval = GetUserName(username, slength)  ' slength is now the length of the returned string

username = Left(username, slength - 1)  ' extract the returned info from the buffer
' (We subtracted one because we don't want the null character in the trimmed string.)
returnUser = username

End Function

Then to call it:

dim strUser as string

strUser = returnUser()

Works in NT, 95, and 98 from my experience
0
 

Author Comment

by:dramaqueen
ID: 2755738
Thanks, tkuppinen, but unless I'm mistaken this function will return the login id and not the full user name (eg, in my case "p0034789" rather than "Andrew James Sharp")

Paasky: that url I just posted seems to do precisely nothing on my machine!
0
 
LVL 1

Expert Comment

by:tkuppinen
ID: 2755781
Sorry
0
 
LVL 10

Expert Comment

by:paasky
ID: 2755862
dramaqueen,

I just got back to home. Give me some time to examine this and I'll try post here something useful.

Paasky
0
 

Author Comment

by:dramaqueen
ID: 2755898
Sob!

I finally managed to cobble together the following and it goes and tells me that I'm the Administrator. NO I'M NOT!!!!

<Weeps uncontrollably>

A.

Option Compare Database
Option Explicit

' definitions not specifically declared in the article:
' the servername and username params can also be declared as Longs,
' and passed Unicode memory addresses with the StrPtr function.
Declare Function NetUserGetInfo Lib "netapi32" _
                              (ByVal servername As String, _
                              ByVal username As String, _
                              ByVal level As Long, _
                              bufptr As Long) As Long
Private Declare Function NetApiBufferFree Lib _
"netapi32" (ByVal pBuffer As Long) As Long
Public Const NERR_Success = 0
Declare Sub MoveMemory Lib "kernel32" Alias _
       "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long
' Converts a Unicode string to an ANSI string
' Specify -1 for cchWideChar and 0 for cchMultiByte to return string length.
Declare Function WideCharToMultiByte Lib "kernel32" _
                            (ByVal codepage As Long, _
                            ByVal dwFlags As Long, _
                            lpWideCharStr As Any, _
                            ByVal cchWideChar As Long, _
                            lpMultiByteStr As Any, _
                            ByVal cchMultiByte As Long, _
                            ByVal lpDefaultChar As String, _
                            ByVal lpUsedDefaultChar As Long) As Long ' CodePage
Public Const CP_ACP = 0        ' ANSI code page
Private Type USER_INFO_3
usri3_name As Long
usri3_password As Long
  usri3_password_age As Long
  usri3_priv As Long
  usri3_home_dir As Long
  usri3_comment As Long
  usri3_flags As Long
  usri3_script_path As Long
  usri3_auth_flags As Long
  usri3_full_name As Long
  usri3_usr_comment As Long
  usri3_parms As Long
  usri3_workstations As Long
  usri3_last_logon As Long
  usri3_last_logoff As Long
  usri3_acct_expires As Long
  usri3_max_storage As Long
  usri3_units_per_week As Long
  usri3_logon_hours As Long
  usri3_bad_pw_count As Long
  usri3_num_logons As Long
  usri3_logon_server As Long
  usri3_country_code As Long
  usri3_code_page As Long
  usri3_user_id As Long
  usri3_primary_group_id As Long
  usri3_profile As Long
  usri3_home_dir_drive As Long
  usri3_password_expired As Long
End Type

Public Function GetFullUserName() As String

  Dim lpBuf As Long
  Dim ui3 As USER_INFO_3
  ' replace "Administrator" with a valid NT username
  If (NetUserGetInfo("", StrConv("Administrator", vbUnicode), 3, lpBuf) = NERR_Success) Then
    Call MoveMemory(ui3, ByVal lpBuf, Len(ui3))
    MsgBox GetStrFromPtrW(ui3.usri3_name)
    GetFullUserName = GetStrFromPtrW(ui3.usri3_password)
    Call NetApiBufferFree(ByVal lpBuf)
  End If
End Function
  ' Returns an ANSI string from a pointer to a Unicode string.
Public Function GetStrFromPtrW(lpszW As Long) As String

Dim sRtn As String
  sRtn = String$(lstrlenW(ByVal lpszW) * 2, 0)   ' 2 bytes/char
' WideCharToMultiByte also returns Unicode string length
'  sRtn = String$(WideCharToMultiByte(CP_ACP, 0, ByVal lpszW, -1, 0, 0, 0, 0), 0)
  Call WideCharToMultiByte(CP_ACP, 0, ByVal lpszW, -1, ByVal sRtn, Len(sRtn), 0, 0)
  GetStrFromPtrW = GetStrFromBufferA(sRtn)
  End Function
' Returns the string before first null char encountered (if any) from an ANSII string.
Public Function GetStrFromBufferA(sz As String) As String
  If InStr(sz, vbNullChar) Then
    GetStrFromBufferA = Left$(sz, InStr(sz, vbNullChar) - 1)
    Else
    ' If sz had no null char, the Left$ function
    ' above would return a zero length string ("").    GetStrFromBufferA = sz
  End If
  End Function

0
 

Author Comment

by:dramaqueen
ID: 2755910
oops..

The line
GetFullUserName = GetStrFromPtrW(ui3.usri3_password)
should of course read
GetFullUserName = GetStrFromPtrW(ui3.usri3_name)

(I was curious about what "password" might return. ... It doesn't return anything in case you're wondering!)

0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:dramaqueen
ID: 2755990
I'm off home now too. I'll come back to this with a clearer head tomorrow.

A.
0
 
LVL 10

Expert Comment

by:paasky
ID: 2756025
oh man.. I seem to have problem booting my NT station at home.

But I see you're almost there, just add the API function which checks the current user and use it with NetUserGetInfo() function:

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

Function fOSUserName() As String
' Returns the network login name
Dim lngLen As Long, lngX As Long
Dim strUserName As String
    strUserName = String$(254, 0)
    lngLen = 255
    lngX = apiGetUserName(strUserName, lngLen)
    If lngX <> 0 Then
        fOSUserName = Left$(strUserName, lngLen - 1)
    Else
        fOSUserName = ""
    End If
End Function


.....
' replace "Administrator" with a valid NT username
  If (NetUserGetInfo("", StrConv(fOSUserName() , vbUnicode), 3, lpBuf) = NERR_Success) Then
....

Paasky
0
 
LVL 10

Expert Comment

by:paasky
ID: 2756029
If you can't make this work, I'll check this thing first in the morning when I get to work with NT workstation.
0
 
LVL 10

Accepted Solution

by:
paasky earned 150 total points
ID: 2756157
Ahh.. finally managed to successfully boot my NT machine. Here's the code which will give you the desired result:

Option Compare Database
Option Explicit

' definitions not specifically declared in the article:
' the servername and username params can also be declared as Longs,
' and passed Unicode memory addresses with the StrPtr function.
Declare Function NetUserGetInfo Lib "netapi32" _
                              (ByVal servername As String, _
                              ByVal username As String, _
                              ByVal level As Long, _
                              bufptr As Long) As Long
Private Declare Function NetApiBufferFree Lib _
"netapi32" (ByVal pBuffer As Long) As Long
Public Const NERR_Success = 0
Declare Sub MoveMemory Lib "kernel32" Alias _
       "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long
' Converts a Unicode string to an ANSI string
' Specify -1 for cchWideChar and 0 for cchMultiByte to return string length.
Declare Function WideCharToMultiByte Lib "kernel32" _
                            (ByVal codepage As Long, _
                            ByVal dwFlags As Long, _
                            lpWideCharStr As Any, _
                            ByVal cchWideChar As Long, _
                            lpMultiByteStr As Any, _
                            ByVal cchMultiByte As Long, _
                            ByVal lpDefaultChar As String, _
                            ByVal lpUsedDefaultChar As Long) As Long ' CodePage
Public Const CP_ACP = 0        ' ANSI code page
Private Type USER_INFO_3
usri3_name As Long
usri3_password As Long
  usri3_password_age As Long
  usri3_priv As Long
  usri3_home_dir As Long
  usri3_comment As Long
  usri3_flags As Long
  usri3_script_path As Long
  usri3_auth_flags As Long
  usri3_full_name As Long
  usri3_usr_comment As Long
  usri3_parms As Long
  usri3_workstations As Long
  usri3_last_logon As Long
  usri3_last_logoff As Long
  usri3_acct_expires As Long
  usri3_max_storage As Long
  usri3_units_per_week As Long
  usri3_logon_hours As Long
  usri3_bad_pw_count As Long
  usri3_num_logons As Long
  usri3_logon_server As Long
  usri3_country_code As Long
  usri3_code_page As Long
  usri3_user_id As Long
  usri3_primary_group_id As Long
  usri3_profile As Long
  usri3_home_dir_drive As Long
  usri3_password_expired As Long
End Type

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

Function fOSUserName() As String
' Returns the network login name
Dim lngLen As Long, lngX As Long
Dim strUserName As String
    strUserName = String$(254, 0)
    lngLen = 255
    lngX = apiGetUserName(strUserName, lngLen)
    If lngX <> 0 Then
        fOSUserName = Left$(strUserName, lngLen - 1)
    Else
        fOSUserName = ""
    End If
End Function


Public Function GetFullUserName() As String

  Dim lpBuf As Long
  Dim ui3 As USER_INFO_3
  If (NetUserGetInfo("", StrConv(fOSUserName(), vbUnicode), 3, lpBuf) = NERR_Success) Then
    Call MoveMemory(ui3, ByVal lpBuf, Len(ui3))
    GetFullUserName = GetStrFromPtrW(ui3.usri3_full_name)
    Call NetApiBufferFree(ByVal lpBuf)
  End If
End Function
  ' Returns an ANSI string from a pointer to a Unicode string.
Public Function GetStrFromPtrW(lpszW As Long) As String

Dim sRtn As String
  sRtn = String$(lstrlenW(ByVal lpszW) * 2, 0)   ' 2 bytes/char
' WideCharToMultiByte also returns Unicode string length
'  sRtn = String$(WideCharToMultiByte(CP_ACP, 0, ByVal lpszW, -1, 0, 0, 0, 0), 0)
  Call WideCharToMultiByte(CP_ACP, 0, ByVal lpszW, -1, ByVal sRtn, Len(sRtn), 0, 0)
  GetStrFromPtrW = GetStrFromBufferA(sRtn)
  End Function
' Returns the string before first null char encountered (if any) from an ANSII string.
Public Function GetStrFromBufferA(sz As String) As String
  If InStr(sz, vbNullChar) Then
    GetStrFromBufferA = Left$(sz, InStr(sz, vbNullChar) - 1)
    Else
    ' If sz had no null char, the Left$ function
    ' above would return a zero length string ("").    GetStrFromBufferA = sz
  End If
  End Function

Usage Example:
? GetFullUserName()
Arto T. Pddskynen

Regards,
Paasky
0
 

Author Comment

by:dramaqueen
ID: 2758655
Thanks, Paasky, but I still can't get it to work. I pasted the code in verbatim, but now it's just returning a blank. Indeed the "IF" condition in the GetFullUserName is not being triggered, so GetFullUserName is not being given a value.
0
 
LVL 10

Expert Comment

by:paasky
ID: 2758687
I think your use priviliges and this problem have to relate somehow. Could you add yourself to Admin group if you're not and then try again. I just copy-pasted above code to my computer at work (NT 4.0 Workstation, SP 6.0) where I'm logged in with my own account that belongs to Administrator group.
0
 

Author Comment

by:dramaqueen
ID: 2758774
I think you could well be right. I don't have administrator priviledges, nor could I get them.

Thanks for your help on this. I'm going to mark this as answered, even though I'm not able to use it. It may well help someone else.

Back to the << Select Case Environ$("UserName") >>  solution!

Cheers,

Andrew
0
 

Author Comment

by:dramaqueen
ID: 2758787
This seems to work, but (a warning to future developers) there seems to be an issue here over NT admin rights. This works for Paasky (who has admin rights)but not for me.
0
 
LVL 10

Expert Comment

by:paasky
ID: 2758806
Guess what, I just added new user account "Test" with only User rights to other NT Workstation and tested above there an it worked there too!!

I believe the issue is you must have a NT domain controller there (we have own accounts in each workstations) where your account information is stored and the function can't get it from there, perhaps because of security restrictions?!

I'm sorry we didn't manage to get the solution which would work for you. Thank you for points anyway.

Regards,
Paasky
0
 
LVL 10

Expert Comment

by:paasky
ID: 2758811
BTW, I'm dying to test this with NT Domain network, but unfortunately I don't have one available... I'll be back to this question if I find suitable test enviroment.
0
 

Author Comment

by:dramaqueen
ID: 2758923
Cheers, Paasky - I appreciate it.
A.
0
 
LVL 1

Expert Comment

by:Alesso
ID: 2778202
Back to the original question, I was using the Environ$("username") to get the system username in Access 97 but learned that it does not work with Windows 95. We have some users who have NT and others who use 95.

Is there a similar statement that is compatible with both?

I will post this as a question as well.

Thanks!
0
 
LVL 10

Expert Comment

by:paasky
ID: 2778248
Hi Alesso,

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

Function fOSUserName() As String
' Returns the network login name
Dim lngLen As Long, lngX As Long
Dim strUserName As String
    strUserName = String$(254, 0)
    lngLen = 255
    lngX = apiGetUserName(strUserName, lngLen)
    If lngX <> 0 Then
        fOSUserName = Left$(strUserName, lngLen - 1)
    Else
        fOSUserName = ""
    End If
End Function

Will give you login name both Win95/98 and WinNT.

? fOsUserName
apaasky

NT system has more and different enviroment variables than Win95/98. You can loop all variables using the following code:

Sub PrintEnvVar()
Dim i As Integer
    For i = 1 To 40
    Debug.Print Environ(i)
    Next
End Sub

Hope this helps,
Paasky
0
 

Author Comment

by:dramaqueen
ID: 2778792
Incidentally, chaps, I think there may be some Novell floating around on our network somewhere; if we're using Netware servers then that might conceivably explain why I had so much trouble with this.
A.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

This article is a continuation or rather an extension from Cascading Combos (http://www.experts-exchange.com/A_5949.html) and builds on examples developed in detail there. It should be understandable alone, but I recommend reading the previous artic…
Overview: This article:       (a) explains one principle method to cross-reference invoice items in Quickbooks®       (b) explores the reasons one might need to cross-reference invoice items       (c) provides a sample process for creating a M…
Learn how to number pages in an Access report over each group. Activate two pass printing by referencing the pages property: Add code to the Page Footers OnFormat event to capture the pages as there occur for each group. Use the pages property to …
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

759 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now