Archive: Using chngvrbl.dll to set $PLUGINSDIR


Using chngvrbl.dll to set $PLUGINSDIR
I am trying to use chngvrbl.dll to set the $PLUGINSDIR variable. The reason for this is my program runs on a USB keychain, and I don't want it to write any files to the hard drive, not even temporarily. I want them all on the USB drive.

However, I am less than brilliant at NSIS, and I could use some help. The code seems to only work for chngvrbl.dll, the other DLLs I call are all still written to the c:..\temp dir. So this implies that $PLUGINSDIR is not actually being changed:

ProfileFound:
StrCpy $9 "$EXEDIR"
SetOutPath $9
File /oname=$9\chngvrbl.dll ${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 25
CallInstDLL "$9\chngvrbl.dll" changeVariable

LaunchProgram:
ExecDos::exec /NOUNLOAD /ASYNC `"$TORDIRECTORY\tor.exe" -f "$TORDIRECTORY\torrc"`
FindProcDLL::FindProc "firefox.exe"


ExecDos and FindProcDLL are still being written to C:, solution? What am I doing wrong?


Well it would be better probably to use CallInstDll to call all the other plugins as well.
You'll have to make a modified copy of Modern UI's Contrib\Modern UI\System.nsh and change it all in there as well. Modern UI also places ioSpecial.ini in there as well, so you could probably just replace $PLUGINSDIR with a different variable and remove any InitPluginsDir instructions. Sounds like a lot of work, but at the end of the day it's less installer overhead.

-Stu


I think what I'm using is already modified for this specific purpose. I just can't seem to implement it correctly. Here is the thread:
http://forums.winamp.com/showthread....=%24pluginsdir

Here is the file:
http://nsis.sourceforge.net/wiki/Change_Variable_Plugin


Try calling InitPluginsDir before StrCpy $9 "$EXEDIR"

-Stu


Still not working. It is like $PLUGINSDIR isn't getting changed at all. Only that CallIstDLL is writing chngvrbl.dll to $9.

InitPluginsDir

StrCpy $9 "$EXEDIR"
SetOutPath $9
File /oname=$9\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 25 ; $PLUGINSDIR
CallInstDLL "$9\chngvrbl.dll" changeVariable
File /oname=$PLUGINSDIR\splash.jpg "${NAME}.gif"
newadvsplash::show /NOUNLOAD 16000 400 400 -1 /L $PLUGINSDIR\splash.jpg


InitPluginsDir has no effect.
After having the message box popup, it still tells me it is in the c: temp:

StrCpy $9 "$EXEDIR"
SetOutPath $9
File /oname=$9\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 25 ; $PLUGINSDIR
CallInstDLL "$9\chngvrbl.dll" changeVariable
MessageBox MB_OK|MB_ICONINFORMATION `The Pluginsdir is now $PLUGINSDIR`


Infact, the Pluginsdir is C:\DOCUME~1\...\Temp\nsq8C1.tmp

It seems that it is compiling as a solid file, instead of a directory. But wait, I checked the compiler and I am only using regular compression, not solid compression. So it should be decompressing into a file. So I checked the script, there is no set compression in there either. So... why is it writing a compressed directory as a file?


Um, do the
InitPluginsDir
right after you call the chngvrbl.dll to change the $PLUGINSDIR.


%TEMP%\nsq8C1.tmp is a directory. Directory names can half dots in as well :p

galil is correct. If you place InitPluginsDir right after the plugin call, $PLUGINSDIR will be set to [my path]\ns####.tmp

-Stu


chgvrbl.dll is written to $EXEDIR, but splash and the rest of my files are still written to C:\%TEMP%

And messagebox still says $PLUGINSDIR is %TEMP%

ProfileFound:
;=== Show the splash screen before processing the files

StrCpy $9 "$EXEDIR"
SetOutPath $9
File /oname=$9\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 25 ; $PLUGINSDIR
CallInstDLL "$9\chngvrbl.dll" changeVariable
InitPluginsDir
MessageBox MB_OK|MB_ICONINFORMATION `The Pluginsdir is now $PLUGINSDIR`

File /oname=$PLUGINSDIR\splash.jpg "${NAME}.gif"
newadvsplash::show /NOUNLOAD 16000 400 400 -1 /L $PLUGINSDIR\splash.jpg


I guess you've got the code in the wrong place. I'm guessing that Modern UI calls InitPluginsDir internally as well. If InitPluginsDir is called before your code snippet then no doubt it won't work. Where are you using your code? Move it to .onInit.

-Stu


It has been moved to the beginning, right after the variables and before the main section. $PLUGINSDIR is still %TEMP%.

...
Var INIPATH
Var ISFILELINE


Function .onInit

StrCpy $9 "$EXEDIR"
SetOutPath $9
File /oname=$9\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 25 ; $PLUGINSDIR
InitPluginsDir
CallInstDLL "$9\chngvrbl.dll" changeVariable
MessageBox MB_OK|MB_ICONINFORMATION `The Pluginsdir is now $PLUGINSDIR`

FunctionEnd

Section "Main"
;=== Find the INI file, if there is one
IfFileExists "$EXEDIR\${NAME}.ini" "" CheckSubINI
StrCpy "$INIPATH" "$EXEDIR\"
Goto ReadINI
....


FOUND THE SOLUTION
InitPluginsDir was the problem. Don't need it!

Function .onInit
StrCpy $9 "$EXEDIR"
SetOutPath $9
File /oname=$9\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 25 ; $PLUGINSDIR
CallInstDLL "$9\chngvrbl.dll" changeVariable
MessageBox MB_OK|MB_ICONINFORMATION `The Pluginsdir is now $PLUGINSDIR`
FunctionEnd

It works! Thanks for the help. I just needed to make sure it was inside .onInit, and that InitPluginsDir was never called.


Well in the code you posted last you did have InitPluginsDir before the plugin call instead of after it. :p

-Stu


InitPluginsDir creates and sets $PLUGINSDIR. If you set it yourself, you don't need to call InitPluginsDir. However, variable number 25 is $TEMP and not $PLUGINSDIR, so you do need InitPluginsDir in order for $PLUGINSDIR to be created in your newly set $TEMP. $PLUGINSDIR is actually number 26, but it's a good thing that you set $TEMP and not $PLUGINSDIR. If you'd have set $PLUGINSDIR to $EXEDIR, $EXEDIR would have been deleted at the end of the installation. When you set $TEMP to $EXEDIR, InitPluginsDir will create a new folder inside $EXEDIR.


repercussions
Now when I call a execdos plugin to run tor.exe, tor terminates instantly. If I remove the pluginsdir code
change, everything is normal again. Seems like the $PLUGINSDIR change code must have something wrong. Any ideas? (nsi included)

the tor.exe log:

Apr 11 20:22:18.640 [notice] Tor v0.1.1.14-alpha. This is experimental software. Do not rely on it for strong anonymity.
Apr 11 20:22:18.640 [notice] Initialized libevent version 1.1a+imweasel using method win32. Good.
Apr 11 20:22:18.640 [warn] Error creating directory tor\data: No such file or directory
Apr 11 20:22:18.640 [err] options_act_reversible(): Couldn't access/create private data directory "tor\data"
Apr 11 20:22:18.640 [err] tor_init(): Reading config failed--see warnings above. For usage, try -h.


Here is my code to call tor.exe:

ExecDos::exec /NOUNLOAD /ASYNC `"$EXEDIR\tor\tor.exe" -f "$EXEDIR\tor\torrc"` "" "$EXEDIR\execdos.log" ; Launch Tor


Here is my code for the pluginsdir change:

Function .onInit
StrCpy $9 "$EXEDIR\temp"
SetOutPath $9
File /oname=$9\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $9
Push 26 ; $PLUGINSDIR
CallInstDLL "$9\chngvrbl.dll" changeVariable
FunctionEnd


Try putting SetOutPath '$EXEDIR\tor' before ExecDos::exec.

-Stu


Everything seemed to work out well. But occaisonally when I terminate the program, I get this error:

"The instruction at '0x0101130e' referenced memory at '0x0101130e'. The memory could not be 'read'.

Click on OK to terminate the program
Click on CANCEL to debug the program"

When I click cancel, nothing seems to happen. Ideas on how to debug or find out where it is coming from?


Why are you terminating the program or are you trying to close it safely?

-Stu


I figured it out. The last plugin I executed used NOUNLOAD and I was forcing it to unload. Problem fixed by calling it again without nounload and async.


That DLL is not working with NSIS 2.37

;NSIS Modern User Interface version 1.70
;Basic Example Script
;Written by Joost Verburg

;--------------------------------
;Include Modern UI

!include "MUI.nsh"

;--------------------------------
;General

;Name and file
Name "Modern UI Test 1.70"
OutFile "Basic.exe"

;Default installation folder
InstallDir "$EXEDIR"

;--------------------------------
;Interface Settings

!define MUI_ABORTWARNING

;--------------------------------
;Pages

!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES

!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS

;--------------------------------
;Languages

!insertmacro MUI_LANGUAGE "English"

Function .onInit

; Use whatever you use to get the user defined temp parameter from $CMDLINE
;Push "/TEMP="
;Call GetParam
;Pop $0
StrCpy $0 "c:\usertemp"

; If the user doesn't pass a parameter just let NSIS determine the $PLUGINSDIR
StrCmp $0 "" nousertemp usertemp
usertemp:
SetOutPath $0
File /oname=$0\chngvrbl_.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $0
Push 25 ; $PLUGINSDIR
CallInstDLL "$0\chngvrbl_.dll" changeVariable
Delete "$0\chngvrbl_.dll"
Goto show
nousertemp:
InitPluginsDir
show:
MessageBox MB_OK|MB_ICONINFORMATION "Pluginsdir: '$PLUGINSDIR'"

FunctionEnd

;--------------------------------
;Installer Sections

Section "Dummy Section" SecDummy

SetOutPath "$INSTDIR"

;ADD YOUR OWN FILES HERE...

;Store installation folder
;WriteRegStr HKCU "Software\Modern UI Test" "" $INSTDIR

;Create uninstaller
;WriteUninstaller "$INSTDIR\Uninstall.exe"

SectionEnd

;--------------------------------
;Descriptions

;Language strings
LangString DESC_SecDummy ${LANG_ENGLISH} "A test section."

;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} $(DESC_SecDummy)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

;--------------------------------

Return-Value is empty :(

#edit after above
i reinstalled nsis to get the original stubs and makensis.exe
- i use the 8192 bytes version. the script above does not work,
but mine do. why? at first - its not at the 8192 version, that
works too - its the InitPluginsDir after that.
first i had this:

Function plugins_dir
StrCpy $0 "$EXEDIR"
StrCmp $0 "" nousertemp
SetOutPath $0
File /oname=$0\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $0
Push 25 ; $PLUGINSDIR
CallInstDLL "$0\chngvrbl.dll" changeVariable
Delete "$0\chngvrbl.dll"
StrCmp $PLUGINSDIR "" nousertemp
Return
nousertemp:
InitPluginsDir
FunctionEnd

now i have that
Function plugins_dir
StrCpy $0 "$EXEDIR"
StrCmp $0 "" nousertemp
SetOutPath $0
File /oname=$0\chngvrbl.dll "${NSISDIR}\Plugins\chngvrbl.dll"
Push $0
Push 25 ; $PLUGINSDIR
CallInstDLL "$0\chngvrbl.dll" changeVariable
Delete "$0\chngvrbl.dll"
nousertemp:
InitPluginsDir
FunctionEnd

the content of pluginsdir is why ever emtpy after the change,
but after InitPluginsDir it has the right pointer to the subdir.

In contrast to written
InitPluginsDir was the problem. Don't need it!
its needed.

Can someone explain it please?