A significant discovery! (for me)

If you are currently developing portable freeware or planning to do so, use this forum to discuss technical implementation, seek out like-minded developers for partnership, or solicit interested users for beta testing.
Post Reply
Message
Author
User avatar
lococobra
Posts: 127
Joined: Fri Aug 03, 2007 10:42 am
Location: USA
Contact:

A significant discovery! (for me)

#1 Post by lococobra » Wed Aug 06, 2008 9:51 pm

I just realized something which some of you probably already know, but I consider it to be the missing link to creating the next step of portibilization scripts.

The methodology behind most of my scripts is...
1. Backup existing settings (rename/move)
2. Move portable settings files/registry into the original location
3. Launch portable app
4. Copy portable settings back to portable drive
5. Restore the backup files

This is a very effective system when dealing with settings and data which are (very) small because it can be done very quickly to the point where the end user doesn't even observe a delay. However, what happens when a program saves a 10mb settings file in the %AppData% folder? This is the problem I've been trying to deal with.

I've tried a million different approaches, including trying to link files, create virtual folders... etc. Nothing works! But now I've found the solution, and it's so obvious.

Here's an example (this is AutoIt code)

Code: Select all

$dir = @ScriptDir&'\Data\Settings'

EnvSet("ALLUSERSPROFILE", $dir)
EnvSet("APPDATA", $dir)
EnvSet("HOMEPATH", $dir)
EnvSet("USERPROFILE", $dir)
EnvSet("PROGRAMFILES", $dir) ;Not sure this is necessary

Run(@ScriptDir&'\App\example.exe')
The effect? The launched program will save any user-specific files to the specified directory. AutoIt sets these variables ONLY for the actual script that's running and any child processes, so other processes won't be saving stuff to your portable AppData dir.

It's a simple idea, but this means that I can now portablize programs which use AppData, My Documents, etc.
Last edited by lococobra on Thu Aug 07, 2008 11:37 am, edited 1 time in total.

User avatar
m^(2)
Posts: 890
Joined: Sat Mar 31, 2007 2:38 am
Location: Kce,PL
Contact:

#2 Post by m^(2) » Wed Aug 06, 2008 10:36 pm

Only badly written ones. It doesn't work with programs that use ShellAPI to retrieve system folder paths, which is the way recommended by MS guidelines.

User avatar
lococobra
Posts: 127
Joined: Fri Aug 03, 2007 10:42 am
Location: USA
Contact:

#3 Post by lococobra » Thu Aug 07, 2008 12:06 am

Hmm, that's strange.... reassigning the environmental variables has worked in every program I've tried so far, except other AutoIt programs.

Is there a way to do a similar redeclaration of... whatever you were talking about?

User avatar
m^(2)
Posts: 890
Joined: Sat Mar 31, 2007 2:38 am
Location: Kce,PL
Contact:

#4 Post by m^(2) » Thu Aug 07, 2008 1:18 am

Sorry, I just tried and I was mistaken.
It's undocumented, but ShellAPI looks for environment variable first.
However, be careful when you do it this way, i.e. getting "My Documents" fails unless "%USERPROFILE%\My Documents" exists...and I guess that exact folder name is language specific. This can lead to instable work of the program. I'm sure it can be made to work well, however doing this well is much more complicated than what you posted.

User avatar
lococobra
Posts: 127
Joined: Fri Aug 03, 2007 10:42 am
Location: USA
Contact:

#5 Post by lococobra » Thu Aug 07, 2008 1:43 am

Well, It's not reliable of course, but most programs just create the folders they need, so by changing the basic env vars, the programs will create their own subdirectories. I'll have to do app-specific testing, but it shouldn't be too hard.

Running that simple script has yielded surprisingly passable results actually.

User avatar
m^(2)
Posts: 890
Joined: Sat Mar 31, 2007 2:38 am
Location: Kce,PL
Contact:

#6 Post by m^(2) » Thu Aug 07, 2008 1:50 am

lococobra wrote:Well, It's not reliable of course, but most programs just create the folders they need, so by changing the basic env vars, the programs will create their own subdirectories. I'll have to do app-specific testing, but it shouldn't be too hard.

Running that simple script has yielded surprisingly passable results actually.
I don't think that many programmers expect that My Documents may not exist. :lol:
The most correct way would be to make a launcher that creates all such problematic directories at startup (reading their names from the registry).
Then the only issue would probably be that in some future Windows version there will be another "known folder" added.

User avatar
lococobra
Posts: 127
Joined: Fri Aug 03, 2007 10:42 am
Location: USA
Contact:

#7 Post by lococobra » Thu Aug 07, 2008 2:15 am

Well, of course it depends on the program. Since when was there ever a single script that worked in every single condition?

I think this should be extremely useful in portablization regardless, and figuring out if it doesn't work because those directories arn't there is easy to test for.

User avatar
m^(2)
Posts: 890
Joined: Sat Mar 31, 2007 2:38 am
Location: Kce,PL
Contact:

#8 Post by m^(2) » Thu Aug 07, 2008 2:45 am

lococobra wrote:Well, of course it depends on the program. Since when was there ever a single script that worked in every single condition?

I think this should be extremely useful in portablization regardless, and figuring out if it doesn't work because those directories arn't there is easy to test for.
Easy to test?
How are you going to test it?
The only method of checking this I can think of is looking into sources and searching for specific phrases (like CSIDL_PERSONAL).

User avatar
lococobra
Posts: 127
Joined: Fri Aug 03, 2007 10:42 am
Location: USA
Contact:

#9 Post by lococobra » Thu Aug 07, 2008 3:04 am

Easy to test = throw the installer/program into sandboxie and see where it puts its files, if it puts some in my documents, then see if the program creates its needed directories when portabilized with my script, if not, then develop some system to automaticly create them.

Seems easy enough to me.

User avatar
m^(2)
Posts: 890
Joined: Sat Mar 31, 2007 2:38 am
Location: Kce,PL
Contact:

#10 Post by m^(2) » Thu Aug 07, 2008 3:36 am

But during the test run you should check all possible execution paths, you often don't know whether you'll come upon a save dialog that defaults to My Documents. Which is practically impossible in complex programs.

User avatar
lococobra
Posts: 127
Joined: Fri Aug 03, 2007 10:42 am
Location: USA
Contact:

#11 Post by lococobra » Thu Aug 07, 2008 11:32 am

You were right, it wasn't quite as simple as I thought it might be, but I've managed to complete a working version of Ziepod, which uses the My Documents folder. Take a look, here's the new functions that I've created to handle everything.

Code: Select all

Func GetAllUsers()
	$AUN = EnvGet('AllUsersProfile')
	$AUNPos = StringInStr($AUN, '\', 0, -1)
	Return StringMid($AUN, $AUNPos+1, StringLen($AUN)-$AUNPos+1)
EndFunc

Func GetNewLoc($dir)
	$User = StringInStr($dir, @UserName, 0, -1)
	$AllUser = StringInStr($dir, $AllUsersName, 0, -1)
	If $User<>0 Then
		$User = $User + StringLen(@UserName)
		$Final = StringMid($dir, $User+1, StringLen($dir)-$User)
	ElseIf $AllUser<>0 Then
		$AllUser = $AllUser + StringLen($AllUsersName)
		$Final = StringMid($dir, $AllUser+1, StringLen($dir)-$AllUser)
	Else
		$Final = ''
	EndIf
	Return $Final
EndFunc

Func SetEnvVars()
	EnvSet("ALLUSERSPROFILE", $SettingsDir)
	EnvSet("APPDATA", $SettingsDir)
	EnvSet("HOMEPATH", $SettingsDir)
	EnvSet("USERPROFILE", $SettingsDir)
EndFunc

Func CreateDataDirs()
	DirCreate($SettingsDir&'\'&GetNewLoc(@AppDataCommonDir))
	DirCreate($SettingsDir&'\'&GetNewLoc(@DocumentsCommonDir))
	DirCreate($SettingsDir&'\'&GetNewLoc(@AppDataDir))
	DirCreate($SettingsDir&'\'&GetNewLoc(@MyDocumentsDir))
	DirCreate($SettingsDir&'\'&GetNewLoc(@UserProfileDir))
	DirCreate($SettingsDir&'\'&GetNewLoc(@DesktopDir))
EndFunc
On the first run, CreateDataDirs() is called, and every time the program is executed, SetEnvVars() is called.

If you see anything that looks like it needs work, please let me know.

User avatar
m^(2)
Posts: 890
Joined: Sat Mar 31, 2007 2:38 am
Location: Kce,PL
Contact:

#12 Post by m^(2) » Thu Aug 07, 2008 1:31 pm

I suggest reading this.
It seems that there's extreme mess in SHGetFolderPath internals and finding a solution that works with majority of programs would be a really daunting task. :?

Post Reply