Announcement

Collapse
No announcement yet.

LoadLibrary Error Information

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • LoadLibrary Error Information

    What am I missing? If I provide an invalid DLL file name to LoadLibrary, I get the expected handle value of zero. But, if I try to get extended error information, I also get zero. The same this is true for (at least) GetProcAddress.
    Code:
    #COMPILE EXE
    
    #INCLUDE "win32api.inc"
    
    FUNCTION PBMAIN () AS LONG
      LOCAL hLib, ret AS LONG
    
      hLib = LoadLibrary("Cabinet.dll")   ' Rtn handle on success or null if fail
      IF hLib = 0 THEN ret = GetLastError ' GetLastError should return specific error
      PRINT "hLib =" hLib " ret =" ret
      IF hLib = 0 THEN GOTO ExitMain
    
    Exitmain:
      IF hLib THEN FreeLibrary hLib
      WAITKEY$
    
    END FUNCTION

  • #2
    You cannot use a literal ( "cabinet.dll") for the library name. The compiler creates a temporary string to pass to the function, then deallocates it when the LoadLibrary function returns.... meaning, the last operation on the thread was not the LoadLibrary() call, it was the call to deallocate the string.. which I have never seen fail, and so GetLastError() will return NO_ERROR. .

    Change your code to use a variable thus...

    Code:
    LOCAL szLib AS WSTRINGZ
    
    sz:Lib  =  "cabinet.dll"
    hlib = LoadLibrary (szLib)
    ...
    .. and you will find GetLastError () will now report the reason.

    MCM
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Michael,
      Thank you, that is good to know!
      I have seen programs with hard-coded names that should be changed.

      Noticed GetLastError should not be used within a USING$ because it always returns 0. STR$(GetLastError) is fine.
      Code:
      %MakeDll = 1 'compile to create DLL, then remark this line and run to test
      
      #IF %DEF(%MakeDll)
       #COMPILE DLL
       SUB TEST EXPORT
        ? FUNCNAME$,,"This is the DLL"
       END SUB
      
      #ELSE
      #INCLUDE "win32api.inc"
      FUNCTION PBMAIN AS LONG
       LOCAL hModule,Address AS DWORD
       LOCAL zModule,zProcName AS ASCIIZ * 257
       zModule = "JUNK.DLL"
       zProcName = "TEST"
       hModule = LoadLibrary(zModule)
       IF hModule THEN
        Address = GetProcAddress(hModule,zProcName)
        IF Address THEN
         CALL DWORD Address
        ELSE
         '? USING$("#",GetLastError) 'don't use USING$ with GetLastError
         ? STR$(GetLastError)
        END IF
        FreeLibrary(hModule)
       ELSE
        ? STR$(GetLastError),,zModule +  " module error"
       END IF
      END FUNCTION
      #ENDIF
      How long is an idea? Write it down.

      Comment


      • #4
        Originally posted by Mike Doty View Post
        I have seen programs with hard-coded names that should be changed.
        You only need to change them if you need to know the specific reason for the library failing to load.
        In many cases a handle of 0 indicating that the file failed to load is all that you need - so a hard coded name is fine.

        Comment


        • #5
          Originally posted by Mike Doty View Post
          Noticed GetLastError should not be used within a USING$ because it always returns 0. STR$(GetLastError) is fine.
          Best practice is to assign the return value of GetLatError to a variable. Then you have it available to convert into an error description using FormatMessage

          Comment


          • #6
            Thanks, Michael. I figured that you would have the answer to this. It works for GetProcAddress as well. Am so glad that you're back!

            Comment


            • #7
              Noticed GetLastError should not be used within a USING$ because it always returns 0. STR$(GetLastError) is fine.
              Probably means USING$ is creating a string into which it will place a formatted value and deallocating it when done. That, of, course A) is proprietary and B) is a guess by me and C) can be avoided by following the "If that does not work, don't do that" rule.

              Michael Mattias
              Tal Systems Inc. (retired)
              Racine WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                Originally posted by Stuart McLachlan View Post
                You only need to change them if you need to know the specific reason for the library failing to load.
                In many cases a handle of 0 indicating that the file failed to load is all that you need - so a hard coded name is fine.
                The part to keep in mind, when a DLL that presumably exists fails to load, is that the cause might also be that one of the DLL's dependencies isn't present and therefore the called DLL - although located where your program assumed/validated it to be - doesn't load. And LoadLibrary will also return 0.

                Comment


                • #9
                  ... when a DLL that presumably exists fails to load, is that the cause might also be....
                  Knuth, it's like Stuart said: sometimes you just don't care WHY the load failed, you only care THAT the load failed.

                  I think the one we see here is, when loading the Richtext control... you might start by trying the "latest and greatest" richtext library and if that does not load because your application is running on an older system, try to load "one release before the latest and greatest. "

                  FWIW, that's one of very few programming tasks I can think of where you can actually have a "Plan B" when a library fails to load.
                  Michael Mattias
                  Tal Systems Inc. (retired)
                  Racine WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment

                  Working...
                  X