Important: you probably shouldn't use this script. If a program uses the native Windows file selection windows (open/save), they will break with APPDATACOMPLEXREDIRECT
, and if a program spawns other programs, you should not redirect APPDATA at all. However, for something simple and straightforward like a game which never spawns any other processes and has no native dialogues or anything like that, you're probably safe to use this script for simple redirection, or for simplicity's sake, just this one line:
System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("APPDATA", "$SETTINGSDIRECTORY").n'
The complex redirection mode is deprecated completely and should not be used. If a program is using a SHGetFolderPath call, move data back and forth rather than trying to redirect it.
(I leave the actual script below for hysterical porpoises.)
Here it is. I think that the code will explain itself to people who need to be interested
This came from my work on Inkscape Portable, and since I've had a couple of other apps which use the complex method, I just decided to make a script out of it. (Note: what actually ended up happening was that I submitted a patch to Inkscape so that the environment variable INKSCAPE_PORTABLE_PROFILE_DIR can be used to override settings location. This is my favourite way of making an application portable, search through the source code and find an environment variable you can override, there very often is, and if not, request it or patch it yourself and submit it for inclusion in the next release.)
AppDataRedirect.nsh
; APPDATA Redirect for PortableApps.com Applications, version 0.2 ; Copyright 2009 Chris Morgan of PortableApps.com ; https://portableapps.com/node/17637 ; Does redirection for apps that depend on APPDATA, with simple and complex handling. ; Released with dual licensing under the GPL version 2 and the BSD license. ; ; USAGE: ; Discover whether you need to do complex or simple redirection. First try simple, ; if that doesn't work, then try complex. ; ; USAGE FOR SIMPLE REDIRECTION: ; When checking to see if the settings directory needs creating, check for/create ; $SETTINGSDIRECTORY ; Before making any modifications to APPDATA settings (e.g. path updating), insert: ; ${RedirectAppData} ; After this, make modifications; APPDATA is still in $SETTINGSDIRECTORY. ; When finished, there is no cleaning-up needed. ; ; USAGE FOR COMPLEX REDIRECTION: ; First of all, before including this file, put in a line of code: ; !define APPDATACOMPLEXREDIRECT ; When checking to see if the settings directory needs creating, check for/create ; $SETTINGSDIRECTORY\${NAME}AppData ; Before making any modifications to APPDATA settings (e.g. path updating), insert: ; ${RedirectAppData} ; After this, make modifications; the new APPDATA can be accessed in the directory ; $SETTINGSDIRECTORY\$CURRENTAPPDATANAME ; When finished, in the clean-up section after ExecWait (i.e. not for a secondary ; launch with Exec) insert: ; ${RevertSettingsLocation} !ifdef APPDATACOMPLEXREDIRECT Var CURRENTAPPDATANAME !endif !macro _AppDataRedirect_RedirectAppData !ifdef APPDATACOMPLEXREDIRECT ; Redirect APPDATA to the settings directory Push $0 ReadEnvStr $0 USERPROFILE ; $0=%USERPROFILE% StrLen $0 $0 ; $0=len($0) IntOp $0 $0 + 1 ; $0=$0+1 (account for the \) StrCpy $CURRENTAPPDATANAME $APPDATA "" $0 ; Set $CURRENTAPPDATANAME to the remainder of APPDATA ; (usually "Application Data" or "AppData", but can be e.g. "AppData\Roaming" ; which is why we can't just leave it at a ${GetFileName} call.) StrCmp $SECONDARYLAUNCH "true" +4 CreateDirectory "$SETTINGSDIRECTORY\$CURRENTAPPDATANAME" ; to take care of a RMDir "$SETTINGSDIRECTORY\$CURRENTAPPDATANAME" ; subdirectory with the rename. Rename "$SETTINGSDIRECTORY\${NAME}AppData" "$SETTINGSDIRECTORY\$CURRENTAPPDATANAME" System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("APPDATA", "$SETTINGSDIRECTORY\$CURRENTAPPDATANAME").n' System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("USERPROFILE", "$SETTINGSDIRECTORY").n' Pop $0 !else System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("APPDATA", "$SETTINGSDIRECTORY").n' !endif !macroend !define RedirectAppData "!insertmacro _AppDataRedirect_RedirectAppData" !ifdef APPDATACOMPLEXREDIRECT !macro _AppDataRedirect_RevertSettingsLocation Rename "$SETTINGSDIRECTORY\$CURRENTAPPDATANAME" "$SETTINGSDIRECTORY\${NAME}AppData" ; Clear out all directories in $SETTINGSDIRECTORY other than the real settings one ; /L=D = directories only, /G=0 = not recursive ; This will also take care of a potential APPDATA subdirectory (see line 43 - "AppData\Roaming") ${Locate} "$SETTINGSDIRECTORY" "/L=D /G=0" "_AppDataRedirect_CleanUserProfile" !macroend !define RevertSettingsLocation "!insertmacro _AppDataRedirect_RevertSettingsLocation" Function _AppDataRedirect_CleanUserProfile ; $R9 = path\name ; $R8 = path ; $R7 = name ; $R6 = size (directory:"", file+/S=:"0") StrCmp $R7 "${NAME}AppData" +2 RMDir /r $R9 Push "" FunctionEnd !include FileFunc.nsh !insertmacro Locate !endif
Release Notes:
0.1 (2009-01-17): Initial Release
0.2 (2009-01-19): fixed roaming profile under Vista