I need to get SMPlayer working and out of the door before tomorrow (I know I'm a procrastinating dev :P) because SMPlayer still hogs CPU and crashes. I was thinking that since SMPlayer uses CSIDL to get folder paths, I could redirect CSIDL like haustin said he would implement into PortableApps.nsh (BTW what happened to it?).
I found a WinAPI article about it, but I'm not entirely sure if it's safe to use. Does it only change it in its own enviroment like the Enviroment Variables, or does it affect the entire system?
Please help and thanks in advance!
Edit: Another WinAPI article
You are here
CSIDL Redirection (ASAP)
August 6, 2008 - 9:44am
#1
CSIDL Redirection (ASAP)
This looks like a permanent redirect unless you change it back. Not sure if admin rights are needed for this. *Probably* not if you're redirecting a user's folder.
This is classified as a "method", I'm not sure how that works in NSIS / AutoIt yet. I'll see if I can figure something out.
EDIT - that Redirect method is Vista only. I don't know how to use it yet, but the IKnownFolderManager interface (of which Redirect is a method) is Vista only.
I guess Vista won't be supported
Now SMPlayer is going to be bulky
Insert original signature here with Greasemonkey Script.
It doesn't matter anyway. As far as I can tell, there's no way to call that Redirect method. Even in AutoIt which has COM Object support (NSIS does not), I cannot find a class to load the IKnownFolderManager interface, so the methods that it covers are unavailable. I'm sure there's a way to do it in a real programming language however.
on the upside that can't be the only way to redirect...
I'll search.
Insert original signature here with Greasemonkey Script.
I'm pretty sure that it's stored somewhere in registry, but I highly recommend to skip it.
-It's gonna mess up local programs.
-In case of a crash / system restart while running etc. these problems won't be temporary. You'll permanently screw host computer.
-It can cause system instability.
Instead, I suggest a hook on SHGetFolderPath. I can offer some help with it.
"Those people who think they know everything are a great annoyance to those of us who do." Asimov
some help would do great.
Insert original signature here with Greasemonkey Script.
Please, nobody reply to this post until digitxp contacts me and I remove my email.
EDIT: I didn't receive any email from digitxp, but lococobra at portablefreeware.com found another solution.
I suggest to do the other solution well. It will take more time, but should be less error prone.
"Those people who think they know everything are a great annoyance to those of us who do." Asimov
You posted when I was asleep ;)...
But that'll work too.
Edit: I already tried Enviroment Variables, but it didn't work
Insert original signature here with Greasemonkey Script.
Maybe you made a mistake somewhere?
Or maybe it behaves differently for some CSIDL values?
Can you post the code that didn't work?
"Those people who think they know everything are a great annoyance to those of us who do." Asimov
Env vars have no effect on the csidl values, at least not on any tests I have tried. I have some AutoIt code I can post if you wanna give it a shot...
Please, do it.
int __cdecl _tmain(int argc, TCHAR ** argv)
{
TCHAR buf[MAX_PATH]={0};
if(FAILED(SHGetFolderPath( 0,CSIDL_PERSONAL|CSIDL_FLAG_CREATE,0,0,buf)))
_tprintf(_T("Failed, error=%d"),GetLastError());
_putts(buf);
return 0;
}
This C code reacts to %USERPROFILE% changes.
"Those people who think they know everything are a great annoyance to those of us who do." Asimov
Perhaps I only tried %USERPROFILE% and not %HOMEDRIVE%%HOMEPATH% or %SYSTEMDRIVE%%HOMEPATH% or %APPDATA%\.. or something. The code is just like any redirection code...
Insert original signature here with Greasemonkey Script.
Are your %USERPROFILE% changes permanent or temporary? We're talking temporary environment changes in this context, so that may make a difference.
AutoIt:
I'll quote my own words from the topic I linked to previously:
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.
In your case %USERPROFILE%\Application Data has to exist, then everything works.
So First, you have to determine all directories that have to be created (By using all CSIDL values, better option would be using all KNOWNFOLDERID values because CSIDL may not be enough for some "Vista or later" programs)
Then you have to find where are their localized names stored in the registry.
Then create these folders in \Data and write a launcher that renames them on startup if locale changed.
"Those people who think they know everything are a great annoyance to those of us who do." Asimov
Well, I retried my example first with $CSIDL_FLAG_CREATE, then after manually creating "C:\test". In all trials, EnvGet("APPDATA") returned "C:\test" correctly, and SHGetFolderPath returned "C:\Users\Erik\AppData\Roaming" (Vista laptop).
So I don't see where the existance of "C:\test" made any difference.
Maybe Vista changed the behaviour, it totally undocumented. Try the following batch (assumes your test program to be named a.exe):
And try it w/out the "create" flag. In my case, when folder exists, it doesn't change anything, it's needed in case that it doesn't. But you cannot assume that app uses this flag, that's why I said to create %USERPROFILE%\Application Data.
"Those people who think they know everything are a great annoyance to those of us who do." Asimov
Ok, very strange results:
EnvGet("APPDATA") = C:\Users\Erik\AppData\Roaming
EnvGet("USERPROFILE") = c:\test
CSIDL_APPDATA = c:\test\AppData\Roaming
CSIDL_LOCAL_APPDATA = c:\test\AppData\Local
CSIDL_PROFILE = C:\Users\Erik
BTW, there's a CSIDL_FLAG_DONT_VERIFY so you don't have to create the directories (for testing purposes).
So it seems that CSIDL_*APPDATA uses the environment var %USERPROFILE%, while CSIDL_PROFILE and environment var %APPDATA% do not. Could MS make this any more confusing?
BTW, there's a CSIDL_FLAG_DONT_VERIFY so you don't have to create the directories (for testing purposes).
For testing purposes - OK, but you need to make it work with all possible sets of flags.
So it seems that CSIDL_*APPDATA uses the environment var %USERPROFILE%, while CSIDL_PROFILE and environment var %APPDATA% do not. Could MS make this any more confusing?
That's why they didn't document how does it work. :D:D
There are still 2 ways. Either play with env vars, but it looks like a daunting task. And will require huge amount of testing, practically with every Windows version.
Hook is a very dirty solution and sometimes antiviruses don't like it. But it can be done in a few hours.
"Those people who think they know everything are a great annoyance to those of us who do." Asimov