Page 1 of 1

Getting the PB installation folder

Posted: Sat Jan 31, 2009 10:26 pm
by Little John
Works also with PB 5.20

Hi all,

for tools such as pre-processors it can be important to know the PB installation folder. When executing a program from the IDE, the folder is

Code: Select all

#PB_Compiler_Home
But how can a stand-alone EXE program know that folder? Well, it can e.g. read the Windows registry, ask the user and/or read a regarding preference file. Here is another way which is simple, reliable and cross-platform.

//edit 2009-03-17: new code

Code: Select all

#SLASH_CHARS$ = "/\"

CompilerSelect #PB_Compiler_OS
   CompilerCase #PB_OS_Windows
      #PB_IDE$ = "purebasic.exe"           ; file name relative to #PB_COMPILER_HOME
   CompilerCase #PB_OS_Linux
      #PB_IDE$ = "compilers/purebasic"
CompilerEndSelect


Procedure.s GetPBFolder()
   ; returns the absolute path of the PB installation directory
   ; (with trailing slash)

 CompilerIf #PB_Compiler_Debugger
   ; The program runs as source code in the IDE with debugger on.
   ProcedureReturn #PB_Compiler_Home

 CompilerElse                                                  ; EXE file
   Protected folder$

   ; First look whether the program runs as IDE tool.
   folder$ = GetEnvironmentVariable("PB_TOOLS_IDE")
   If folder$
      ProcedureReturn Left(folder$, Len(folder$)-Len(#PB_IDE$))
   EndIf

   ; Look for a regarding environment variable on the system.
   folder$ = GetEnvironmentVariable("PUREBASIC_HOME")
   If folder$
      If FindString(#SLASH_CHARS$, Right(folder$,1),1) = 0
         folder$ + "/"
      EndIf
      ProcedureReturn folder$
   EndIf

   ; The program runs as standalone program, and the environment variable PUREBASIC_HOME is not set.
   ; In this case, the executable file must be in a SUBDIRECTORY of the PB installation directory.
   folder$ = GetPathPart(ProgramFilename())
   Repeat
      folder$ = GetPathPart(Left(folder$, Len(folder$)-1))  ; parent folder
      If folder$ = ""
         Break
      EndIf
   Until FileSize(folder$ + #PB_IDE$) > 0
   ProcedureReturn folder$
 CompilerEndIf
EndProcedure
Regards, Little John

Posted: Sun Feb 01, 2009 12:41 am
by AND51
If the standalone EXE is below the PureBasic.exe, you can also use relative paths:

Code: Select all

Procedure.s GetPBFolder(depth=32)
	Protected n, path.s="PureBasic.exe"
	For n=0 To depth
		If FileSize(path) > 0
			ProcedureReturn path
		EndIf
		path="..\"+path
	Next
EndProcedure

MessageRequester("", GetPBFolder())

Posted: Sun Feb 01, 2009 12:45 am
by AND51
3 lines more and you can also get absolute path (with a small workaround):

Code: Select all

Procedure.s GetPBFolderAbsolute(depth=32)
	Protected n, path.s=".\", current.s=GetCurrentDirectory()
	For n=0 To depth
		If FileSize(path+"PureBasic.exe") > 0
			SetCurrentDirectory(path)
			path=GetCurrentDirectory()
			SetCurrentDirectory(current)
			ProcedureReturn path+"PureBasic.exe"
		EndIf
		path+"..\"
	Next
EndProcedure

MessageRequester("", GetPBFolderAbsolute())
Or is there anoter way to convert relative paths into absolute ones?

Posted: Sun Feb 01, 2009 7:51 am
by Little John
AND51 wrote:3 lines more and you can also get absolute path (with a small workaround)
That's what my code did anyway. I can't see an advantage by doing it with your method.

Regards, Little John

Posted: Mon Feb 02, 2009 12:56 pm
by AND51
The difference is, that with my code, the standalone EXE may be ANY NUMBER of directories below the PB-directory.

Your code does simply this:

Code: Select all

path$ = "..\PureBasic.exe"
But with the difference, that it does not return the absolute path like this piece of code, but it returns the absolute path.

With my codes, the depth does not matter. The standalone EXE can be located in .\compilers, .\libraries or .\libraries\userlibraries and so on; o matter, as it alsways finds the right level upwards.

I hope you can understand my english in this post. :)

Posted: Wed Feb 04, 2009 1:26 pm
by Little John
AND51 wrote:The difference is, that with my code, the standalone EXE may be ANY NUMBER of directories below the PB-directory.
I see now that your code is searching for the PB installation folder. For that purpose, I'd prefer something like this (especially because the CurrentDirectory is not necessarily the directory where your program is located!):

Code: Select all

//edit 2009-03-17: Code removed (see first post)
Regards, Little John

Posted: Wed Feb 04, 2009 3:16 pm
by AND51
Little John wrote:I'd prefer something like this (especially because the CurrentDirectory is not necessarily the directory where your program is located!)
Yeah, you're right.
But imho it's more secure and faster, if you work with relative paths. That's why I put ".." before the path, each time I need to go a directory upwards.

That's what my first procedure does. It just returns the relative path.

My second procedure does the same, but it turns the relative path to an absolute one by using Set/GetCurrentDirectory(). I just don't know an other solution for how to convert relative to absolute paths.

Posted: Wed Feb 04, 2009 4:00 pm
by Little John
AND51 wrote:
Little John wrote:I'd prefer something like this (especially because the CurrentDirectory is not necessarily the directory where your program is located!)
Yeah, you're right.
But imho it's more secure and faster, if you work with relative paths.
The primary question is, what is required by the program that uses such a routine. That might be a relative path in a particular context, and an absolute path in another context. Sometimes maybe it doesn't matter. It depends.
AND51 wrote:My second procedure does the same, but it turns the relative path to an absolute one by using Set/GetCurrentDirectory(). I just don't know an other solution for how to convert relative to absolute paths.
This also depends. The question is: Relative to what?
If you want to convert a path that is relative to the current directory, use GetCurrentDirectory() for conversion.
If you want to convert a path that is relative to the directory where your own program is located, use GetPathPart(ProgramFilename()) for conversion.

Regards, Little John