api GetUserName not working properly - error: Bad DLL calling convention

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Seth Schrock
    Recognized Expert Specialist
    • Dec 2010
    • 2965

    api GetUserName not working properly - error: Bad DLL calling convention

    I'm attempting to use an api to get the username of the currently logged in Windows user. I've basically copied and pasted the function from Function to return Username

    Here is the code that I'm using:
    Code:
    Declare Function GetUserName Lib "advapi32.dll" Alias _
                         "GetUserNameA" (ByVal lpBuffer As String, nSize As Long)
    
    Public Function fGetUserName()
    
    'Get current Windows user name
    Dim strUser
    Dim s$, cnt&, dl&
    Dim max_String As Integer
     
        max_String = 30
        cnt& = 199
        s$ = String$(max_String, 1)
        dl& = GetUserName(s$, cnt)
        strUser = Trim$(Left$(s$, cnt))
        strUser = UCase(Mid(strUser, 1, Len(strUser) - 1))
    
    
    
    'Get user ID
    Application.TempVars.Add "UserID", DLookup("EmployeeID", "tblEmployee", "Username = '" & strUser & "'")
    Debug.Print Application.TempVars("UserID").Value
    
    'Get user type
    Application.TempVars.Add "UserType", DLookup("EmployeeType", "tblEmployee", "Username = '" & strUser & "'")
    Debug.Print Application.TempVars("UserType").Value
    
    
    End Function
    However, I'm getting an error message on line 14 that says
    Run-time error '49':

    Bad DLL calling convention


    I looked it up in MSDN and found Bad DLL calling convention. I understand absolutely nothing in the page so I'm going to need help.
  • NeoPa
    Recognized Expert Moderator MVP
    • Oct 2006
    • 32633

    #2
    It's because Mary's shockingly sloppy :-D

    Add the & to cnt to refer to the actual variable cnt&.

    Comment

    • Seth Schrock
      Recognized Expert Specialist
      • Dec 2010
      • 2965

      #3
      Same error. Here is my line 14 now
      Code:
       dl& = GetUserName(s$, cnt&)
      I also added the & to the cnt in line 15. Did I need to?

      Comment

      • NeoPa
        Recognized Expert Moderator MVP
        • Oct 2006
        • 32633

        #4
        I'm not sure exactly what the problems are Seth, but here's some code to try that I know works for me :
        Code:
        Private Declare Function GetUserName Lib "advapi32.dll" _
            Alias "GetUserNameA" (ByVal lpBuffer As String, _
                                  lpnSize As Long) As Long
        
        'GetLogonName() determines the logon ID of the current user.
        Public Function GetLogonName() As String
            Dim lngMax As Long
            Dim strBuffer As String
        
            lngMax = &HFF
            strBuffer = String(lngMax, vbNullChar)
            Call GetUserName(lpBuffer:=strBuffer, lpnSize:=lngMax)
            GetLogonName = Trim(Left(strBuffer, lngMax - 1))
        End Function
        Originally posted by Seth
        Seth:
        I also added the & to the cnt in line 15. Did I need to?
        Yes. That would have been necessary in the previous code, I believe.

        Comment

        • TheSmileyCoder
          Recognized Expert Moderator Top Contributor
          • Dec 2009
          • 2322

          #5
          You could try this instead:
          Code:
          Public Function GetLoginName() as string
            GetLoginName= CreateObject("wscript.network").UserName
          End Function

          Comment

          • NeoPa
            Recognized Expert Moderator MVP
            • Oct 2006
            • 32633

            #6
            I may be wrong for current versions of the OS Smiley, but I don't believe the WScript engine (or the CScript one either - assuming they are separate) is loaded by default. If that is still the case then loading it will cause some extra overhead. I'm certain it would work, but is not so light footprinted as one might imagine from the tidiness of the code.

            On the other hand, it is much smaller as far as the code goes, so may appeal to many for that reason.

            Comment

            • TheSmileyCoder
              Recognized Expert Moderator Top Contributor
              • Dec 2009
              • 2322

              #7
              Valid point, but then again, what does the API call of the previous mentioned method involve?

              Some timing scores for the function I posted when used from Access 2010 and Windows 7:
              [1] iterations performed in:0ms
              [100] iterations performed in:31ms
              [1000] iterations performed in:343ms

              Some timing scores for the function I copied from post #4:
              [1] iterations performed in:0ms
              [100] iterations performed in:16ms
              [1000] iterations performed in:62ms



              I would argue that in the end it makes little difference, as its not a function you will call hundreds of times (at a time) anyway.
              Last edited by TheSmileyCoder; Jan 15 '13, 04:41 PM.

              Comment

              • NeoPa
                Recognized Expert Moderator MVP
                • Oct 2006
                • 32633

                #8
                Originally posted by Smiley
                Smiley:
                I would argue that in the end it makes little difference, as its not a function you will call hundreds of times (at a time) anyway.
                I would suggest that indicates that the timing test was not an appropriate one. The API is calling code which is already loaded. The WScript option requires extra code to be loaded into RAM (and thus tie up that extra RAM). That load would never need to be repeated, so tests of running it multiple times would only tend to hide the 'cost' rather than illustrate it. Thus, it is a resources issue rather than a timing one I was referring to.

                Personally, I believe that well mannered software should always aim to increase its footprint only when necessary, so until WScript is incorporated as standard into the OS I use it as little as I can (Which is a shame as I'm sure you appreciate that what it can offer is very extensive).

                PS. You would probably find, if you were interested in looking into it that deeply, that the calls themselves would end up as performing very comparably and the extra overhead is simply due to the repeated interpreting of the lines of code within the function I posted in post #4. Again, not something that repetition throws any light on, but makes sense if you understood my earlier comment to be simply about performance (which as you rightly say is totally negligible).
                Last edited by NeoPa; Jan 15 '13, 05:01 PM. Reason: Added PS.

                Comment

                • Seth Schrock
                  Recognized Expert Specialist
                  • Dec 2010
                  • 2965

                  #9
                  Strangly enough, the error was in the GetUserName function. I replaced mine with yours and it worked perfectly. The only difference that I can see is that you have a private function and you have changed the variable name from nSize to lpnSize. I'm not sure if this actually matters, but that is all I see different.

                  As to which method to use, I'll play around with it and see. I do have the answer to my original question though.

                  Thanks NeoPa and Smiley for your assistance and advice.

                  By the way, why didn't the compiler find the variable with the missing &? I have Option Explicit set.
                  Last edited by Seth Schrock; Jan 15 '13, 05:00 PM. Reason: added question

                  Comment

                  • NeoPa
                    Recognized Expert Moderator MVP
                    • Oct 2006
                    • 32633

                    #10
                    Originally posted by Seth
                    Seth:
                    By the way, why didn't the compiler find the variable with the missing &? I have Option Explicit set.
                    Good question. I'm not sure is my answer. Maybe it recognises it with or without and it didn't need the & added after all. I never use such names as they have been de-recommended. They only still work to support old code.

                    They are an echo from very much older versions of BASIC where Dim etc didn't even exist. I don't believe that MS ever recommended they be used for serious work (Fine if you're knocking up a quick equation on a calculator or similar device of course).

                    Comment

                    • zmbd
                      Recognized Expert Moderator Expert
                      • Mar 2012
                      • 5501

                      #11
                      I should point out... my IT has disabled WScript via GPO in all general user accounts. Only Admin and certain "poweruser" accounts have the rights to run scripting.
                      I've had to redo my "install" method and my front-end updater because of this "lockout" as both used script files.

                      Comment

                      • TheSmileyCoder
                        Recognized Expert Moderator Top Contributor
                        • Dec 2009
                        • 2322

                        #12
                        Ouch bummer. Certainly something to be aware of.
                        Can you use Shell commands? I use a Shell command to launch a database containing my update code, so its all native access except the shell command.

                        I don't know much about how WScript and GPO functions. Have you tried the code in post #5? Did it error? I would like to know as it could mean I ought to rethink some things.

                        Comment

                        • zmbd
                          Recognized Expert Moderator Expert
                          • Mar 2012
                          • 5501

                          #13
                          I have one of those "special" accounts; thus, I didn't know anything was wrong until one of my error traps started sending me emails. I had altered the backend tables; thus, the frontend update... worked fine on my PC... not so well on the boss' PC. Simple point and click via IT fixed but involved a lot of paperwork.

                          Therfor, I'll not be able to test your code in my work setting; however, here's a link covering the basics: Security Settings for WSH Scripts from what IT has told me this link is still the root method, just with Windows7 a fancier interface.

                          Comment

                          • TheSmileyCoder
                            Recognized Expert Moderator Top Contributor
                            • Dec 2009
                            • 2322

                            #14
                            Did your method use wscript in a manor similar to mine, or was the script external to access? I.e. a script file being run from access?
                            Last edited by zmbd; Jan 22 '13, 03:35 PM. Reason: [z{sent pm}]

                            Comment

                            • NeoPa
                              Recognized Expert Moderator MVP
                              • Oct 2006
                              • 32633

                              #15
                              I'm pretty sure the code from post #5 would fail if WScript were blocked Smiley, as it invokes WScript within the CreateObject() call.

                              Comment

                              Working...