Link to home
Start Free TrialLog in
Avatar of dramaqueen
dramaqueen

asked on

Get username alias from NT

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?
Avatar of paasky
paasky
Flag of Finland image

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
Avatar of dramaqueen
dramaqueen

ASKER

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.
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
Here's the link which saves you for re-inventing the wheel:

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

Hope this helps,
Paasky
Adjusted points from 50 to 150
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.
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

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
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!
Sorry
dramaqueen,

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

Paasky
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

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!)

I'm off home now too. I'll come back to this with a clearer head tomorrow.

A.
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
If you can't make this work, I'll check this thing first in the morning when I get to work with NT workstation.
ASKER CERTIFIED SOLUTION
Avatar of paasky
paasky
Flag of Finland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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.
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
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.
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
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.
Cheers, Paasky - I appreciate it.
A.
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!
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
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.