Solved

Get username alias from NT

Posted on 2000-04-27
27
558 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

 
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
 

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

[Webinar] Learn How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

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

This article describes two methods for creating a combo box that can be used to add new items to the row source -- one for simple lookup tables, and one for a more complex row source where the new item needs data for several fields.
The Windows Phone Theme Colours is a tight, powerful, and well balanced palette. This tiny Access application makes it a snap to select and pick a value. And it doubles as an intro to implementing WithEvents, one of Access' hidden gems.
Basics of query design. Shows you how to construct a simple query by adding tables, perform joins, defining output columns, perform sorting, and apply criteria.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

627 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