Archive: Directory where ${__FILE__} is located?


Directory where ${__FILE__} is located?
Hi everyone,

I know about the compiler variable ${__FILE__} which returns the name of the file that is currently being compiled.

Is there a way to get the directory where that file is located?

Basically I want to create a sort of "shared NSIS stuff" directory that all of my scripts can access. In there I want to place a file called "MyOptions.nsh" which uses InstallOptions and requires "MyOptions.ini".

So the problem is, if I have "ProductA.nsi" do this:

!addincludedir "..\..\SharedNSIS"
!include "MyOptions.nsh"

then the compile fails, because obviously NSIS will not look in the "include" dirs for an INI file.

For now I have modified MyOptions.nsh so that the full path to MyOptions.ini is hardcoded -- but this is bad, because other developers might place the source tree in a different location on their workstations.

If "MyOptions.nsh" could determine its own path, then I'd be all set.

Thanks for your help... and NSIS guys, thank you for the excellent software.

-- graham


I think the NSIS dev should add a ${__PATH__} constant.
You could then just use ${__PATH__}\${__FILE__}.

-Stu


Code?
I'm looking at the NSIS sources for the first time, and it looks rather straightforward to me. This is all in "script.cpp" as far as I can see. Maybe this code will provide a starting point:


char *CEXEBuild::set_path_predefine(char *filename)
{
char *oldpath = definedlist.find("__PATH__");
if(oldpath)
{
definedlist.del("__PATH__");
}
char *p = strrchr(filename, '\\\');
if(p)
{
char *filepath = strdup(filename);
filepath[p - filename] = '\0';
definedlist.add("__PATH__", filepath);
}
return oldpath;
}

void CEXEBuild::restore_path_predefine(char *oldpath)
{
char *curpath = definedlist.find("__PATH__");
if(curpath)
{
free(curpath);
definedlist.del("__PATH__");
}
if(oldpath) {
definedlist.add("__PATH__",oldpath);
}
}


Then just add these to the class definition, and call them at the same time you'd call set_file_predefine and restore_file_predefine.

NSIS devs, please verify this code before you check it in. It looks okay to me, but I haven't tested it (or even tried to compile it).

Thanks

-- graham

For now you can use !system to redirect the output of the `cd` command into a file. For example:

!system 'echo !define __PATH__ \ > $%TEMP%\PATH.nsh'
!system 'cd >> $%TEMP%\PATH.nsh'
!include $%TEMP%\PATH.nsh

I've just tried this, if you add the above code by kickik to a file b.nsh and include it from a.nsi, __PATH__ will contain the parent directory of a.nsi, how can we determine the parent of b.nsh in this case?


If you want it at build time, simply append two dots "${__PATH__}\..". If you want it at runtime, you can use GetParent for a nicer looking path.


nope, that didnt work

I have a.nsi on the desktop and b.nsh in C:\, so it's not just going up one directoy, any other ideas?


In that case, you can simply use:

!include "\b.nsh"
makensis automatically changes the working directory to that of the script it compiles.

yep that works out, but the problem is i got a bunch of other files/resources that b.nsh uses and those files are always going to be in the same directory as b.nsh, so I wanted to make the code in b.nsh be able to reference those files in its directory. Then if I change the location of the include in a.nsi to C:\abc\123\b.nsh, nothing else would need changing


Then you're looking for the path of b.nsh, not a.nsi. You can use a similar trick, but instead of calling 'cd', call a program that'd convert b.nsh's ${__FILE__} into ${__PATH__}. It could be a simple silent NSIS installer that'd call GetParent and write the result into a file.

# in b.nsh
!system "GetParent.exe ${__FILE__}"
!include "$%TEMP%\PATH.nsh"

!echo "${__PATH__}"

thanks, i'll try it out