Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question about 'fGetFullNameOfLoggedUser'

25 views
Skip to first unread message

Douglas Buchanan

unread,
Jun 20, 2003, 9:40:03 PM6/20/03
to
The code below "Code 1": 'fGetFullNameOfLoggedUser' comes from Dev
Ashish's site.

I want to save the name of the user for each record entered.

These are the options I've tried:

1.) Running it each time a new record is opened - This is way too
slow!!!

2.) Trying to assign the procedure name to a constant is not allowed.

3.) Having the 'switchboard' (the startup form) assign a global
variable in the form's Load or Open event slows down the opening of
that form.

4.) Trying "Code 2" 'GetUserName' (see further below) from VBnet - I
could not get it to run. I think I was missing a reference - But which
one?!? I tried browsing and selected "advapi32.dll" (the code
references this) - I get an error saying "Can't add a referece to the
specified file." What does that mean?

• What other options are there to achieve my goal?
• Is there code that runs faster?
• Am I making trying to add "advapi32.dll" incorrectly?
• Is there a 'perceived' speed technique I can use - like something
with a timer to run the code after the 'Switchboard' has come into
view?

' ******** Code 1 Start ********
'This code was originally written by Dev Ashish.
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code Courtesy of
'Dev Ashish
'
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

' function frees the memory that the NetApiBufferAllocate
' function allocates.
Private Declare Function apiNetAPIBufferFree _
Lib "netapi32.dll" Alias "NetApiBufferFree" _
(ByVal buffer As Long) _
As Long

' Retrieves the length of the specified wide string.
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

' moves memory either forward or backward, aligned or unaligned,
' in 4-byte blocks, followed by any remaining bytes
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 Const MAXCOMMENTSZ = 256
Private Const NERR_SUCCESS = 0
Private Const ERROR_MORE_DATA = 234&
Private Const MAX_CHUNK = 25
Private Const ERROR_SUCCESS = 0&

Function fGetFullNameOfLoggedUser(Optional strUserName As String) As
String
'
' Returns the full name for a given UserID
' NT/2000 only
' Omitting the strUserName argument will try and
' retrieve the full name for the currently logged on user
'
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 (Len(strUserName) = 0) 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))
fGetFullNameOfLoggedUser = fStrFromPtrW(pTmp.usri2_full_name)
End If

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

Private 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

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

Private 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
' ******** Code 1 End *********

' ******** Code 2 Start ********
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2003 VBnet, Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you may not reproduce
' or publish this code on any web site,
' online service, or distribute as source
' on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const MAX_USERNAME As Long = 15

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

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

Private Function GetThreadUserName() As String

'Retrieves the user name of the current
'thread. This is the name of the user
'currently logged onto the system. If
'the current thread is impersonating
'another client, GetUserName returns
'the user name of the client that the
'thread is impersonating.
Dim buff As String
Dim nSize As Long

buff = Space$(MAX_PATH)
nSize = Len(tmp)

If GetUserName(buff, nSize) = 1 Then

GetThreadUserName = TrimNull(buff)
Exit Function

End If

End Function


Private Function TrimNull(startstr As String) As String

TrimNull = Left$(startstr, lstrlenW(StrPtr(startstr)))

End Function
' ******** Code 2 End *********

Albert D. Kallal

unread,
Jun 20, 2003, 11:06:08 PM6/20/03
to
It would seem that option #3 is the most reasonable. You will only execute
the function once. I mean, how much better then that can you get?

In many appcltions I log:

ms-access logon name
I use CurrentUser() function to get this

workstation logon name
http://www.mvps.org/access/api/api0008.htm

workstation computer name.
http://www.mvps.org/access/api/api0009.htm

So, in theory, you could just log the workstation logon name. I find that
code runs fast. In fact, it does not take a round trip to the server to grab
the "full" name. Further, by using the NT logon name, you limit the
platforms that your code will run on. Each windows workstation ALWAYS has a
logon name, but you can't be sure that your users will be connected to a
nt/win2000 server box (so, in single user mode your code is not workable).
If users are on a peer to peer network, then no full username is available
anyway.

I would probably dump the grabbing of the full user name from the server,
and just use the workstation logon name as above. Both the server logon, and
the workstation logon name are going to be the same logon id anyway. I can't
see why you need the full user name in place of the logon name? Especially
if this is just for logging purposes, then just dump the full user name.
Further, you can always create a table of full user names for reports etc if
you MUST for some strange reasons show a full name in some of those reports.


--
Albert D. Kallal (MVP)
Edmonton, Alberta Canada
kal...@msn.com


David W. Fenton

unread,
Jun 21, 2003, 1:48:44 PM6/21/03
to
kal...@msn.com (Albert D. Kallal) wrote in
<AYPIa.249205$ro6.6...@news2.calgary.shaw.ca>:

>It would seem that option #3 is the most reasonable. You will only
>execute the function once. I mean, how much better then that can
>you get?

And if you wrap the process in class module, it can be
self-healing, so that if the code gets reset, simply referring to
it again will cause it to re-initialize.

This is accomplished by having the lookup in the class module's
Initialize event.

And the way class modules work is that if you have a global
variable for the class module, any reference to that class module
will cause it to initialize itself if it has not already been
instantiated.

Another option would be to maintain a table of users on the server
that includes user logon name and user full-name. Your code could
check that table to see if the user's name has already been looked
up from the server and, if not, do the slow lookup and insert the
record. That would remain accurate as long as the full name is not
changed on the server, and how often does *that* happen?

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc

Douglas Buchanan

unread,
Jun 27, 2003, 4:19:55 PM6/27/03
to
Albert,

This was perfect! Much faster than the code I was using.

Thank you,
Doug

"Albert D. Kallal" <kal...@msn.com> wrote in message news:<AYPIa.249205$ro6.6...@news2.calgary.shaw.ca>...

0 new messages