Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
16 Views

how to get a console program's folder location at run time

This question is specific to the Windows OS.  Is the code below the recommended way for a console program to get the folder in which it is located at run time?  Note I do not want the "current working folder" or "default path".  I want the location of the EXE file.  This code is from a very old post.

Subroutine get_exe_path(gpth,npth) !get exe path from cmd line 
    implicit none 
    integer, intent(out)          :: npth 
    character(len=*), intent(out) :: gpth 
    integer                       :: ilen, istat   
    character(len=512)            :: garg 
    gpth=' ' 
    npth=0 
    call get_command_argument (0, garg, ilen, istat) !an intrinsic function
    if(istat == 0) then 
        npth=index(garg,'\',.true.) !an intrinsic function, true means search backward
        gpth=garg(1:npth) 
    endif 
end subroutine

 

0 Kudos
11 Replies
Highlighted
Valued Contributor I
16 Views

I use a different WinAPI; in

I use a different WinAPI; in the example, the .exe file is always located in a \bin subdirectory to the root directory for the program itself:

!   get local root path from opsys
localroot = ''
nc = GetModuleFileName(GetModuleHandle('MYPROG.EXE'C), fpname, LEN(fpname))
IF (nc > 0) THEN
    CALL updncase (fpname, 1)
    nc = INDEX(fpname, '\BIN\MYPROG.EXE')
    IF (nc > 0) localroot = fpname(1:nc - 1)
END IF

 

0 Kudos
Highlighted
Valued Contributor III
16 Views

I suggest Windows API

I suggest Windows API GetModuleFileName also as indicated in Quote #2:

https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamea

Re: "way for a console program to get the folder in which it is located at run time," note in Microsoft documentation, "A handle to the loaded module whose path is being requested. If this parameter is NULL, GetModuleFileNameretrieves the path of the executable file of the current process."

You may know Intel Fortran team provides an interface to said API in their KERNEL32 Fortran module:

https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-supplied-windows-api...

0 Kudos
Highlighted
Beginner
16 Views

Thanks.  Is this recommended

Thanks.  Is this recommended over using pure fortran ?  If so, why?  I prefer an all fortran approach in case this code is ever ported to Unix.  The following is a slight revision I plan  to use.  When I append the name of a file to gpth, I evidently have to use TRIM(gpth).  How does one take advantage of automatic deallocation and reallocation of strings such that gpth = gpth(1:len(trim(gpth))) would shorten the string?

Subroutine get_exe_path(gpth) !get exe path from cmd line with trailing backslash 
    implicit none 
    character(len=*), intent(out) :: gpth 
    integer                       :: ilen, istat, i
    character(len=4096)           :: s 
    call get_command_argument(0, s, ilen, istat) 
    i=0
    if(istat == 0) i = index(s,'\',.true.) 
    gpth = ' '
    if(i .gt. 0) gpth = s(1:i)
end subroutine  

0 Kudos
Highlighted
New Contributor II
16 Views

Hi

Hi

Your approach will not work under windows if the program is launched from a console without path in the command line (program in current directory or in the path).

Ex:

cd programdir

program.exe

args[0] will contain only "program.exe"

GetModuleFilename is the unique solution under windows.

 

 

 

 

0 Kudos
Highlighted
Beginner
16 Views

I see what you mean, and I

I see what you mean, and I confirmed it with a test.  The following seems to do the trick:

Subroutine get_exe_path(exepath) !get exe path with trailing backslash
    use KERNEL32
    implicit none 
    character(len=*), intent(out) :: exepath 
    integer                       :: ilen, i
    character(len=4096)           :: s 
    ilen = GetModuleFileName(NULL, s, 4096) 
    i = index(s,'\',.true.) 
    exepath = ' '
    if(i .gt. 0) exepath = s(1:i)
end subroutine 

 

0 Kudos
Highlighted
16 Views

I am not sure about Linux

I am not sure about Linux when the program is launched via Symbolic Link. IOW does arg[0] contain the path of the Symbolic Link or the path of the target of the Symbolic Link. This is something you would have to check out.

Jim Dempsey

0 Kudos
Highlighted
Beginner
16 Views

What is IOW?  The need to

What is IOW?  The need to support Unix/Linux is not absolutely required at this time.  Please correct me if I'm wrong, but since the Fortran standard does not provide a way for an executable to determine the folder where it is located, I'll use the Windows API to get it.  I suppose it makes sense that doing so would be OS dependent.  The reason for wanting the location of this folder is to access other files which are co-located with the EXE file.  In this case those other files are being read, but are not written to.

0 Kudos
Highlighted
Black Belt
16 Views

IOW = In Other Words

IOW = In Other Words

You are correct that the Fortran standard does not specify a method to do what you want.  On Windows, GetModuleFileName is exactly correct if you want a path to the executable.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
New Contributor II
16 Views

If you want your code  to be

If you want your code  to be OS independent, the path separator will in every case be a problem. You must write a function that determine the current OS and first set the actual path separator \ for Windows, / for Linux. Then you must write path management functions and use them everywhere in your code where you use pathes. And so on  It's not as so easy as it may appear at the first look.

 

Grouping all OS dependent subroutines, functions and constants in an "OS" named module may be a good approch. You only have to link the appropropriate module to generate the exe for a specific OS

 

0 Kudos
Highlighted
Beginner
16 Views

The immediate need is just

The immediate need is just Windows.  Since supporting another OS depends on the OS, that will be addressed when the need arises.

0 Kudos
Highlighted
New Contributor II
16 Views

Yes, immediately not, but if

Yes, immediately not, but if you do the job for Windows now, the work to implement another OS will be half done because you will not have to review all your code to port the program to Linux, but just write a new OS module and link it to the rest of the code.

 

 

0 Kudos