PowerBASIC Peer Support Forums
 

Go Back   PowerBASIC Peer Support Forums > User to user Discussions > Programming

Programming User to user discussions of general programming topics such as algorithms, APIs, etc.

Reply
 
Thread Tools Display Modes
  #1  
Old Jul 28th, 2008, 02:43 AM
Ian Bayly Ian Bayly is offline
Member
 
Join Date: Jul 2008
Location: Christchurch New Zealand
Posts: 68
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
Reply With Quote
  #2  
Old Jul 28th, 2008, 03:10 AM
Petr Schreiber jr Petr Schreiber jr is offline
 
Join Date: Oct 2006
Posts: 783
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
Reply With Quote
  #3  
Old Jul 28th, 2008, 03:22 AM
Wayne Diamond Wayne Diamond is online now
Member
 
Join Date: Sep 2000
Location: A land down under
Posts: 2,316
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
__________________
PBCrypto Archive - Archived!
Reply With Quote
  #4  
Old Jul 28th, 2008, 03:30 AM
Mike Stefanik Mike Stefanik is offline
Member
 
Join Date: Dec 2004
Location: California
Posts: 1,989
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.
__________________
Mike Stefanik
www.catalyst.com

Last edited by Mike Stefanik; Jul 28th, 2008 at 03:34 AM.
Reply With Quote
  #5  
Old Jul 28th, 2008, 04:01 AM
Ian Bayly Ian Bayly is offline
Member
 
Join Date: Jul 2008
Location: Christchurch New Zealand
Posts: 68
Great response from all of you!

Thanks heaps.

Ian B
Reply With Quote
  #6  
Old Jul 28th, 2008, 10:53 AM
StanHelton StanHelton is offline
Member
 
Join Date: Aug 2007
Location: Huntsville, AL
Posts: 361
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
__________________
StanHelton PC and LAN
stanhelton.com
The VB6 to PowerBASIC Converter Project
Reply With Quote
  #7  
Old Jul 28th, 2008, 11:20 AM
Wayne Diamond Wayne Diamond is online now
Member
 
Join Date: Sep 2000
Location: A land down under
Posts: 2,316
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
__________________
PBCrypto Archive - Archived!
Reply With Quote
  #8  
Old Jul 28th, 2008, 11:27 AM
jcfuller jcfuller is online now
Member
 
Join Date: Aug 1998
Location: Fort Edward, NY
Posts: 1,327
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
  
'#########################################################################
Reply With Quote
  #9  
Old Jul 28th, 2008, 12:14 PM
Mike Stefanik Mike Stefanik is offline
Member
 
Join Date: Dec 2004
Location: California
Posts: 1,989
Quote:
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.
__________________
Mike Stefanik
www.catalyst.com

Last edited by Mike Stefanik; Jul 28th, 2008 at 04:37 PM. Reason: Fixed a couple of typos
Reply With Quote
  #10  
Old Jul 28th, 2008, 12:16 PM
Mike Stefanik Mike Stefanik is offline
Member
 
Join Date: Dec 2004
Location: California
Posts: 1,989
Quote:
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
www.catalyst.com
Reply With Quote
  #11  
Old Jul 28th, 2008, 01:36 PM
Wayne Diamond Wayne Diamond is online now
Member
 
Join Date: Sep 2000
Location: A land down under
Posts: 2,316
Quote:
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.
__________________
PBCrypto Archive - Archived!

Last edited by Wayne Diamond; Jul 28th, 2008 at 01:55 PM.
Reply With Quote
  #12  
Old Jul 28th, 2008, 03:42 PM
Michael Mattias Michael Mattias is offline
Member
 
Join Date: Aug 1998
Location: Racine WI USA
Posts: 36,256
>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
mailto:mmattias@talsystems.com
www.talsystems.com
Reply With Quote
  #13  
Old Jul 28th, 2008, 05:22 PM
StanHelton StanHelton is offline
Member
 
Join Date: Aug 2007
Location: Huntsville, AL
Posts: 361
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:
Quote:
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
__________________
StanHelton PC and LAN
stanhelton.com
The VB6 to PowerBASIC Converter Project
Reply With Quote
  #14  
Old Jul 28th, 2008, 06:20 PM
Paul Squires Paul Squires is offline
Member
 
Join Date: Oct 2000
Posts: 2,086
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
Reply With Quote
  #15  
Old Jul 28th, 2008, 06:42 PM
Michael Mattias Michael Mattias is offline
Member
 
Join Date: Aug 1998
Location: Racine WI USA
Posts: 36,256
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
mailto:mmattias@talsystems.com
www.talsystems.com
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 06:54 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Copyright 1999-2011 PowerBASIC, Inc. All Rights Reserved.
Error in my_thread_global_end(): 1 threads didn't exit