Getting the directory of executable (like GetModuleFileName)

Discussion of Common Lisp
MicroVirus
Posts: 11
Joined: Sat Apr 07, 2012 6:20 am

Getting the directory of executable (like GetModuleFileName)

Post by MicroVirus » Sun May 27, 2012 3:35 pm

Dear Lispers,

I've been writing a small HTTP server and I'd like to deploy it to a friends computer. To allow some configuration to be done per machine, I want to add a settings file (like 'setting.ini' for other applications) to the same directory as the program will be in, so it can read in the settings from that file. I've yet to write the full code for it, but I think I'll manage, but one thing has stumped me so far and too many google searches have delivered nothing of use :(
How do I get the directory in which the (lisp) program is running? Like the Win32 GetModuleFileName, which can be used to get the current process' filename.
Is there any Lisp function that can do that? I'm guessing it'll become something tied specifically to the implementation, so in that case: I'm using CLisp.
Thanks in advance for your input.

Best Regards,

Richard

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Getting the directory of executable (like GetModuleFileN

Post by edgar-rft » Sun May 27, 2012 4:16 pm

I'm not really sure how CLISP behaves on Windows, but one of the following should work:

MicroVirus
Posts: 11
Joined: Sat Apr 07, 2012 6:20 am

Re: Getting the directory of executable (like GetModuleFileN

Post by MicroVirus » Mon May 28, 2012 6:35 am

Thanks for your reply Edgar. Unfortunately, those both use the current working directory when the program starts, which (at least on Windows) is highly unpredictable and not a reliable method.
If in the command line the user uses the following two ways to open the program, the results would differ:

Code: Select all

D:\Mydir> myprogram.exe
-> runs myprogram with cwd set to D:\Mydir\

D:\> mydir\myprogram.exe
-> runs myprogram with cwd set to D:\
So I can't use that, unfortunately.

But, your reply did make me look again at the CLisp ext: functionality, and despite its name I think I might have found what I needed: EXT:ABSOLUTE-PATHNAME.
The documentation says: (EXT:ABSOLUTE-PATHNAME pathname) converts the pathname to a physical pathname, then - if its directory component is not absolute - converts it to an absolute pathname, by merging in the current process' directory.
So I think I could pass it "." and get the root directory of the process. Can anyone confirm that this works reliably?

Thanks for pointing me in the right direction, though to be honest I do think it odd that Lisp doesn't have that functionality built in or under a more telling name.

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Getting the directory of executable (like GetModuleFileN

Post by edgar-rft » Mon May 28, 2012 7:20 am

MicroVirus wrote:I think I could pass "." to EXT:ABSOLUTE-PATHNAME and get the root directory of the process.
This will not work for several reasons:
  • On Windows the root directory is the parent directory of the drive-letters, which is not accessible at all.
  • "." is a file name , "./" is a directory name. EXT:ABSOLUTE-PATHNAME can't return a directory name if you specify a file name as argument. CLISP is very picky in this regard.

Code: Select all

[4]> (absolute-pathname "./")
#P"/home/edgar/test/"
[5]> (default-directory)
#P"/home/edgar/test/"
There is a CLISP symbol-macro CUSTOM:*LIB-DIRECTORY* (that can be read and set like a variable). If you're lucky then on Windows this will return either the directory of the "clisp.exe" launcher or the "lib/" subdirectory of the "clisp.exe" launcher directory:

Code: Select all

[6]> *lib-directory*
#P"/usr/lib/clisp-2.48/"
This was tested with CLISP 2.48 (obsolete) on Debian Linux. I have no Windows here to test it.

MicroVirus
Posts: 11
Joined: Sat Apr 07, 2012 6:20 am

Re: Getting the directory of executable (like GetModuleFileN

Post by MicroVirus » Wed Jun 06, 2012 3:54 pm

I managed to test it on Windows and you are right. All the described methods return the same thing: the current working directory.
I've given up on getting the executable's directory for now, I'll just have to ensure the current working directory is properly set.

I've now stumbled upon a new problem with distribution though :( I want my application to start up without creating a console window, so basically as a background process with no visible windows. I've found this link http://www.frank-buss.de/lisp/clisp.html describing a method to create the executable image without a console window, but have been unsuccessful at building my own CLisp so far (on Win32, using MinGW as described).

I'm going to be busying myself with getting this part to work now :) Thanks for your help.

pjstirling
Posts: 166
Joined: Sun Nov 28, 2010 4:21 pm

Re: Getting the directory of executable (like GetModuleFileN

Post by pjstirling » Thu Jun 07, 2012 3:49 am

(ASDF:SYSTEM-RELATIVE-PATHNAME system name) may do what you want

Konfusius
Posts: 62
Joined: Fri Jun 10, 2011 6:38 am

Re: Getting the directory of executable (like GetModuleFileN

Post by Konfusius » Thu Jun 07, 2012 3:50 pm

You may use *load-truename*. While loading this variable is bound to the name and full path of the lisp-file that is currently loading. Since it is only bound while loading you cannot use it directly in your program. You have to assign it to a global variable and then use that instead:

Code: Select all

(defparameter *install-path* (make-pathname :name nil :type nil :defaults *load-truename*)) ; remove name and extension from truename

MicroVirus
Posts: 11
Joined: Sat Apr 07, 2012 6:20 am

Re: Getting the directory of executable (like GetModuleFileN

Post by MicroVirus » Fri Jun 08, 2012 6:22 pm

Thanks for your reply. I'll try out *load-truename* as soon as I can. I am very curious if it is properly bound when using an executable created with saveinitmem.

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Getting the directory of executable (like GetModuleFileN

Post by edgar-rft » Sat Jun 09, 2012 3:56 am

Several things to consider:
  • It's generally not desirable to have a function returning the location of the executable, because this opens the door and invites all virii of the internet to manipulate the executable.
  • Windows provides several mechanisms for storing configuration files (e.g. C:\Documents and Settings\... etc.). But note that all these places are localized in non-english Windows versions. Windows provides environment variables like USERPROFILE and similar with the localized names of all these directiories, and CLISP provides an EXT:GETENV function to read environment variables. Read the Windows documentation for the names of the directories and environment variables.
ASDF is not part of CLISP and *LOAD-TRUENAME* will surely not work in a dumped image, as long as no Lisp file is loaded.

sinnatagg
Posts: 29
Joined: Tue Apr 21, 2009 3:04 am

Re: Getting the directory of executable (like GetModuleFileN

Post by sinnatagg » Fri Jun 15, 2012 12:26 am

MicroVirus wrote:Thanks for your reply. I'll try out *load-truename* as soon as I can. I am very curious if it is properly bound when using an executable created with saveinitmem.
You need to check both *load-truename* and *compile-file-truename* since your code may be either evaluated or compiled.

My preferred approach is to query the sysdef facility (i.e. asdf) for the location of the system and then add the relative location of the config file.


-andré

Post Reply