Announcement

Collapse
No announcement yet.

VB6 App.path

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

  • VB6 App.path

    Hi
    As a new migrant from VB I miss the app.path function.
    I've spent several hours searching PB forums with no success.
    Is there a PB equivalent or maybe an API call I haven't yet found?
    I looked at API "GetCommandLine" but it didn't work for me!
    TIA

    Ian B

  • #2
    Hi,

    I presume APP.Path returns application path?


    Petr

    Code:
      DECLARE FUNCTION GetModuleFileName LIB "KERNEL32.DLL" ALIAS "GetModuleFileNameA" (BYVAL hModule AS DWORD, lpFileName AS ASCIIZ, BYVAL nSize AS DWORD) AS DWORD
      DECLARE FUNCTION GetModuleHandle LIB "KERNEL32.DLL" ALIAS "GetModuleHandleA" (lpModuleName AS ASCIIZ) AS DWORD
    
      FUNCTION AppPath() AS STRING
        LOCAL hModule     AS DWORD
        LOCAL sBuffer     AS ASCIIZ * 256
        LOCAL thePath     AS STRING
        LOCAL slashPos    AS LONG
    
        hModule = GetModuleHandle(BYVAL 0&)
        
        ' -- From handle we extract path to EXE, including its name
        GetModuleFileName hModule, sBuffer, 256
    
        ' -- We need just path, so we seek for any \/ from right to left
        thePath   = TRIM$(sBuffer)
        slashPos = INSTR(-1,thePath, ANY "\/")
        
        ' -- If we havent found slash, we return all, but most probably we will return the
        ' -- string up to last \/ occurience
        FUNCTION = IIF$(slashPos > 0, LEFT$(thePath, slashPos), thePath )
    
      END FUNCTION
    petrschreiber@gmail.com

    Comment


    • #3
      Code:
      FUNCTION AppPath() AS STRING
       LOCAL buffer AS ASCIIZ * %MAX_PATH
       GetModuleFileName GetModuleHandle(BYVAL 0&), buffer, SIZEOF(buffer)
       FUNCTION = LEFT$(buffer, INSTR(-1, buffer, "\"))
      END FUNCTION
       
      FUNCTION AppExeName() AS STRING
       LOCAL buffer AS ASCIIZ * %MAX_PATH
       GetModuleFileName GetModuleHandle(BYVAL 0&), Buffer, %MAX_PATH
       FUNCTION = Buffer
      END FUNCTION
      -

      Comment


      • #4
        Code:
        FUNCTION GetAppPath() AS STRING
            DIM szPathName AS ASCIIZ * %MAX_PATH
            DIM cchPathName AS DWORD
            DIM nIndex AS LONG
            
            cchPathName = GetModuleFileName(0, szPathName, %MAX_PATH)
            IF cchPathName > 0 THEN
                nIndex = INSTR(-1, szPathName, "\")
                IF nIndex > 1 AND MID$(szPathName, nIndex - 1, 1) <> ":" THEN
                    nIndex = nIndex - 1
                END IF
                FUNCTION = LEFT$(szPathName, nIndex)
            ELSE
                GetCurrentDirectory(%MAX_PATH, szPathName)
                FUNCTION = szPathName
            END IF
        END FUNCTION
        One thing to watch for is that if the executable is installed off the root, you don't want to just strip to the last "\" character because then you'll get something like "C:" returned, and "C:" and "C:\" aren't the same thing. Technically that call to GetCurrentDirectory should never happen, but I tend to have a paranoid coding style, so if GetModuleFileName fails, I'd punt and hand back the current directory.
        Last edited by Mike Stefanik; 28 Jul 2008, 02:34 AM.
        Mike Stefanik
        sockettools.com

        Comment


        • #5
          Great response from all of you!

          Thanks heaps.

          Ian B

          Comment


          • #6
            Mike,

            Do you mind if we use your function in the vb2pb Converter? It solves a common problem and I hate re-inventing the wheel.

            Thanks,
            Stan
            Do not go quiet into that good night,
            ... Rage, rage against the dark.

            Comment


            • #7
              GetCurrentDirectory shouldn't be used to get the applications path because unlike the applications path which is static the current directory of the process can change if it issues commands such as CHDIR/CHDRIVE
              -

              Comment


              • #8
                Another one compliments of Hutch.

                James
                Code:
                '#########################################################################
                  
                  FUNCTION AppPath() as STRING
                  
                    #REGISTER NONE
                
                      LOCAL PathBuffer as ASCIIZ * 128
                  
                      GetModuleFileName ByVal %NULL,PathBuffer,128
                      adr& = VarPtr(PathBuffer)
                      var& = 0
                  
                        ! xor ecx, ecx
                        ! xor edx, edx
                        ! mov esi, adr&
                      bfrStart:
                        ! lodsb
                        ! inc ecx
                        ! cmp al, 0     ; exit on zero
                        ! je bfrOut
                        ! cmp al, "\"
                        ! jne bfrStart
                        ! mov edx, ecx  ; put position of ecx count in edx
                        ! jmp bfrStart
                      bfrOut:
                        ! mov var&, edx
                  
                      FUNCTION = lcase$(left$(PathBuffer,var&))
                  
                  END FUNCTION
                  
                '#########################################################################

                Comment


                • #9
                  Originally posted by Wayne Diamond View Post
                  GetCurrentDirectory shouldn't be used to get the applications path because unlike the applications path which is static the current directory of the process can change if it issues commands such as CHDIR/CHDRIVE
                  Note that it only calls GetCurrentDirectory if GetModuleFileName fails. Of course, you could change that to meet whatever particular needs your application has, but given that most programs are started with their current working directory being their application folder, and this kind of function would be typically called at application startup (presumably as a means to build filenames), it's not an unreasonable fallback condition to take.

                  Generally speaking, I'm not just comfortable calling any Windows API function assuming that it will succeed. An alternative would be to throw up message box or print something to standard error indicating that there was an unexpected failure in the GetModuleFileName function.
                  Last edited by Mike Stefanik; 28 Jul 2008, 03:37 PM. Reason: Fixed a couple of typos
                  Mike Stefanik
                  sockettools.com

                  Comment


                  • #10
                    Originally posted by StanHelton View Post
                    Do you mind if we use your function in the vb2pb Converter? It solves a common problem and I hate re-inventing the wheel.
                    Sure, you can use it (or any other code that I post here).
                    Mike Stefanik
                    sockettools.com

                    Comment


                    • #11
                      Note that it only calls GetCurrentDirectory if GetModulePathName fails.
                      Yes but GetModuleFilename in the way i've posted above shouldn't ever fail - if it does something is very, very wrong.

                      And that's not to say that it can't fail, because security software or rootkits for example might hook in and for some reason or another cause it to fail. I think like you Mike - everything can fail! (even when it seems impossible)

                      But if it does fail I don't think you should try to 'fall back' on any other attempts to get the application path, especially not ones that can return incorrect results such as GetCurrentDirectory. I think it's best to return either nothing or an errorcode rather than a result that may-or-may-not be accurate, because if GetModuleFileName is failing then something is seriously wrong.

                      And as for GetCurrentDirectory, it simply returns the directory the current process has an open handle to - it has nothing to do with the path of the executable, so it can't be relied upon to return the directory of the app exe.

                      There are various alternatives to GetModuleFilename ... you could for example call GetCurrentProcessId and traverse the process list, but there's just no need - GetModuleFilename should always work to get your app exe's path.
                      Last edited by Wayne Diamond; 28 Jul 2008, 12:55 PM.
                      -

                      Comment


                      • #12
                        >GetModuleFilename should always work to get your app exe's path

                        True enough, but a potential 'gotcha:' GetModuleHandle(BYVAL %NULL) always returns a handle to the EXE, even when it's called from a function in a loaded DLL.

                        To get the name/path of the DLL file, you need to use the hInst passed to LibMain when the DLL is attached to the calling process.

                        MCM
                        Michael Mattias
                        Tal Systems Inc.
                        Racine WI USA
                        mmattias@talsystems.com
                        http://www.talsystems.com

                        Comment


                        • #13
                          As I've said before elsewhere, I favor DDT and I'm working on learning SDK coding. There's an awful lot to learn.

                          bold added by me:
                          Originally posted by Michael Mattias View Post
                          >GetModuleFilename should always work to get your app exe's path

                          True enough, but a potential 'gotcha:' ...

                          To get the name/path of the DLL file, you need to use the hInst passed to LibMain when the DLL is attached to the calling process.

                          MCM
                          Please pardon my cerebral density here, but how would that look in code?

                          Stan
                          Do not go quiet into that good night,
                          ... Rage, rage against the dark.

                          Comment


                          • #14
                            Code:
                            Global ghInstance As Long
                            
                            
                            Function LibMain(ByVal hInstance   As Long, _
                                             ByVal fwdReason   As Long, _
                                             ByVal lpvReserved As Long) Export As Long
                            
                               ghInstance = hInstance
                            
                            ...etc....
                            Paul Squires
                            FireFly Visual Designer (for PowerBASIC Windows 10+)
                            Version 3 now available.
                            http://www.planetsquires.com

                            Comment


                            • #15
                              Actually, Paul, I would not do it on each entry to LibMain, I'd do it only once, on the DLL_PROCESS_ATTACH notification.

                              No sense wasting CPU cycles, is there?

                              Not that an integer assignment is a whole lot of overhead; however, it is the judgement of this court you are penalized three (3) style points for doing anything needlessly.

                              MCM
                              Michael Mattias
                              Tal Systems Inc.
                              Racine WI USA
                              mmattias@talsystems.com
                              http://www.talsystems.com

                              Comment

                              Working...
                              X