C:\Documents and Settings\All Users\Application Data
by Very Interactive Person · in Torque Game Builder · 12/28/2006 (5:11 am) · 17 replies
I've asked this question before in the TGE forums, thinking I'd get more response there, but I didn't get much more then advice to not do it this way. But I'm stubborn, and I really want to to it this way.
So what am I trying to do? Well i want to add a console function that will give me the path to "C:\Documents and Settings\All Users\Application Data". This folder is there for a purpose, and microsoft encourages developers to use it. I want to write some data to that folder, so if you uninstall the game, that data isn't lost (and is still available when you re-install the game).
My problems now:
-How to ask the OS for this path (its not always the same, for 90% of XP users its probably "C:\Documents and Settings\All Users\Application Data", but not for all of them)
-How to make it accesible trough Torque script
-What about win 98 /ME/... any idea if there's a similar folder? If not, this function should probably return an empty string on those operating systems.
-I heard there's a similar folder on Mac systems. Offcourse I would like this to work on Mac too (offcourse on Mac that's a different folder...)
May sound like a basic task to some of you. But for me... well, I haven't played with the C++ part of TGB much. I try to do everything in script, so I'm a bit lost here.
If nobody wants to help here...I'm willing to pay some small cash for it. Contact me if your time isn't free (but remember I'm an indie, in fact this is more like a hobby... and I'm far from rich :) )
So what am I trying to do? Well i want to add a console function that will give me the path to "C:\Documents and Settings\All Users\Application Data". This folder is there for a purpose, and microsoft encourages developers to use it. I want to write some data to that folder, so if you uninstall the game, that data isn't lost (and is still available when you re-install the game).
My problems now:
-How to ask the OS for this path (its not always the same, for 90% of XP users its probably "C:\Documents and Settings\All Users\Application Data", but not for all of them)
-How to make it accesible trough Torque script
-What about win 98 /ME/... any idea if there's a similar folder? If not, this function should probably return an empty string on those operating systems.
-I heard there's a similar folder on Mac systems. Offcourse I would like this to work on Mac too (offcourse on Mac that's a different folder...)
May sound like a basic task to some of you. But for me... well, I haven't played with the C++ part of TGB much. I try to do everything in script, so I'm a bit lost here.
If nobody wants to help here...I'm willing to pay some small cash for it. Contact me if your time isn't free (but remember I'm an indie, in fact this is more like a hobby... and I'm far from rich :) )
#2
That's the easy part. If you want to actually do anything useful with said directory from script, it's not so easy. The resource manager prevents you from accessing anything outside of the game directory. There is a hack (in stock Torque) to allow you to read files from anywhere if they can't be found through the resource manager ... it may or may not be enabled by default for TGB. It is for TGE. To actually write anything to that directory may require additional hacking. Even with the above two hacks you will not be able to scan the directory with findFirstFile() etc.
To do that you'd need to add the directory to the resource manager. You can hack that by adding it to the mod paths, but you are pretty much guaranteed that that path has spaces in so you can't just add it to the list of mods and expect it to work, since that list is space separated. setModPaths() itself takes a semi colon separated list so you can hack it on the end before calling it, but then anything that modifies the mod paths later on probably won't work properly. Also expandos like ~ and . won't work from that directory and there is a ton of code that won't like you giving it full paths.
It gets progressively more hellish from there depending on how actually useful you want getting the directory to be. If you just want to use it to save prefs, you might be OK with the huge caveats. If you do all your I/O to that directory in C++, you can use FileStream directly and thus bypass the resource manager and most of the issues, but then you can't use scripts unless you read the whole file into memory and hand it off to Con::evaluatef() (same way as the top level main.cs is handled). Calling exec() from the script won't work in that case due to the location of the file, but that may be OK for prefs.
Trust me when I say that if you are sure you want to go down this route, you are in for a LOT of hairloss. I would only reccomend doing it now if your project is close to finished, you absolutely need to do it, you only use it for simple prefs and you have a significant amount of hair.
T.
12/29/2006 (7:37 am)
Read the MSDN docs for SHGetSpecialFolderPath(), add a new TGB Platform function that uses it, add a ConsoleFunction that calls said new platform function and returns the string to script. The Platform function would have to be implemented for each platform (obviously), I don't remember the Mac equivalent offhand.That's the easy part. If you want to actually do anything useful with said directory from script, it's not so easy. The resource manager prevents you from accessing anything outside of the game directory. There is a hack (in stock Torque) to allow you to read files from anywhere if they can't be found through the resource manager ... it may or may not be enabled by default for TGB. It is for TGE. To actually write anything to that directory may require additional hacking. Even with the above two hacks you will not be able to scan the directory with findFirstFile() etc.
To do that you'd need to add the directory to the resource manager. You can hack that by adding it to the mod paths, but you are pretty much guaranteed that that path has spaces in so you can't just add it to the list of mods and expect it to work, since that list is space separated. setModPaths() itself takes a semi colon separated list so you can hack it on the end before calling it, but then anything that modifies the mod paths later on probably won't work properly. Also expandos like ~ and . won't work from that directory and there is a ton of code that won't like you giving it full paths.
It gets progressively more hellish from there depending on how actually useful you want getting the directory to be. If you just want to use it to save prefs, you might be OK with the huge caveats. If you do all your I/O to that directory in C++, you can use FileStream directly and thus bypass the resource manager and most of the issues, but then you can't use scripts unless you read the whole file into memory and hand it off to Con::evaluatef() (same way as the top level main.cs is handled). Calling exec() from the script won't work in that case due to the location of the file, but that may be OK for prefs.
Trust me when I say that if you are sure you want to go down this route, you are in for a LOT of hairloss. I would only reccomend doing it now if your project is close to finished, you absolutely need to do it, you only use it for simple prefs and you have a significant amount of hair.
T.
#3
Anyway, thanks. (btw, I just found the SHGetSpecialFolderPath(), was just about to post it here so I could get better directions on where to go from here, then I saw your reply :) ). Like I said, I'm not at all familiar with the engine code, and my C++ is rusty (actually worse then that :) )... I hope I can manage from here.
12/29/2006 (7:55 am)
Quote:The resource manager prevents you from accessing anything outside of the game directoryI want to acces text files and parse those. This works just fine (already doing it with hard-coded paths).
Quote:I would only reccomend doing it now if your project is close to finishedIt is :) Actually it is "finished". I'm preparing it so it can be published. And now I want to change some minor things, like where certain files are stored.
Anyway, thanks. (btw, I just found the SHGetSpecialFolderPath(), was just about to post it here so I could get better directions on where to go from here, then I saw your reply :) ). Like I said, I'm not at all familiar with the engine code, and my C++ is rusty (actually worse then that :) )... I hope I can manage from here.
#4
I just need a console function that returns me this path, and if this path doesn't exist it can return me an empty string (so on win 98 for example it'll return an empty string (i think)). I would really like to have something similar on Mac, so like Tom said, it should be a platform function. If you can only do the windows part, but set it up so i can later add the mac function, that's fine too. I really need to finish this game asap.
12/30/2006 (3:44 am)
Anyone out there want to make a quick 20$ (for an experienced programmer this shouldnt take more then half an hour I believe)? Tried to add it, but I'm losing way too much time with it.I just need a console function that returns me this path, and if this path doesn't exist it can return me an empty string (so on win 98 for example it'll return an empty string (i think)). I would really like to have something similar on Mac, so like Tom said, it should be a platform function. If you can only do the windows part, but set it up so i can later add the mac function, that's fine too. I really need to finish this game asap.
#5
12/31/2006 (7:46 am)
... and a free copy of the game :)
#6
The correct way seems to be more than a few lines of code worth, from a cursory glance at documentation I have,
so I'd have to look into the Win32 way of doing it. SHGetSpecialFolderLocation() is a function that is available
even in the Win95 API, although there are better ways on 2000+.
Is $HOME/.appname/ the right way to store personal configuration on Mac OS X? If so, the same code
can be shared between all Unix builds and Mac. This is the "easy" bit.
Making it available to scripts takes even more reading. I'm not too steady with the innards yet, but it's of interest
to me to have this sort of functionality.
To test the Mac hypothesis, open a console/terminal on yer trusty Mac and type "ls -la" from the $HOME path.
If you see lots of .directories, some should have application names. If you don't see a single familiar word
there, someone more used to Mac innards needs to look at it.
12/31/2006 (4:18 pm)
I'm amazed this isn't already in the engine as a cross-platform convenience feature!The correct way seems to be more than a few lines of code worth, from a cursory glance at documentation I have,
so I'd have to look into the Win32 way of doing it. SHGetSpecialFolderLocation() is a function that is available
even in the Win95 API, although there are better ways on 2000+.
Is $HOME/.appname/ the right way to store personal configuration on Mac OS X? If so, the same code
can be shared between all Unix builds and Mac. This is the "easy" bit.
Making it available to scripts takes even more reading. I'm not too steady with the innards yet, but it's of interest
to me to have this sort of functionality.
To test the Mac hypothesis, open a console/terminal on yer trusty Mac and type "ls -la" from the $HOME path.
If you see lots of .directories, some should have application names. If you don't see a single familiar word
there, someone more used to Mac innards needs to look at it.
#7
This has been discussed a few times, but the base reason is that core Torque is designed with several security decisions, including -never- allowing the Torque executable to write to a directory outside of it's root.
This is to keep people from using TorqueScript to do nasty things to your files when they shouldn't be. Re-wiring TGB to allow full seamless use of any directory is not a trivial task, as Tom describes--intentionally.
12/31/2006 (6:00 pm)
Quote:
I'm amazed this isn't already in the engine as a cross-platform convenience feature!
This has been discussed a few times, but the base reason is that core Torque is designed with several security decisions, including -never- allowing the Torque executable to write to a directory outside of it's root.
This is to keep people from using TorqueScript to do nasty things to your files when they shouldn't be. Re-wiring TGB to allow full seamless use of any directory is not a trivial task, as Tom describes--intentionally.
#8
@ronny: I bought me a second hand mac mini last week, I'll see tonight if I can find the folder where we are supposed to write to.
01/02/2007 (4:44 am)
Quote:This is to keep people from using TorqueScript to do nasty things to your files when they shouldn't beBut writing textfiles outside of the mod dir seems to work just fine (or am i wrong? I tried "../../" to get out of the mod dir, and even out of the application folder, and I can write there, no problem. I can also read the file back in. I also checked if the isFile function works when you enter a full path, works fine too. So, I have everything I need, just need the path now :)
@ronny: I bought me a second hand mac mini last week, I'll see tonight if I can find the folder where we are supposed to write to.
#9
01/03/2007 (12:05 pm)
Grrr... still not getting it to compile. Anyone? Like I said, I'm willing to pay for your time.
#10
Here are the changes.
The bold text is the code I've added.
File: platform\platform.h
Line: 349
------------------------------------------------------------------------------
File: platformWin32\winFileio.cc
Line: 710
------------------------------------------------------------------------------
File: platformWin32\platformWin32.h
Line: 21
------------------------------------------------------------------------------
File: console\consoleFunctions.cc
Line: 1467
Here's my testing from console log (Win XP SP2)
Hope this helps.
01/04/2007 (7:16 am)
I've got it working in Windows :)Here are the changes.
The bold text is the code I've added.
File: platform\platform.h
Line: 349
static StringTableEntry getWorkingDirectory(); [b]static StringTableEntry getUserDirectory(); static StringTableEntry getCommonUserDirectory();[/b] static StringTableEntry getExecutableName();
------------------------------------------------------------------------------
File: platformWin32\winFileio.cc
Line: 710
StringTableEntry Platform::getWorkingDirectory()
{
static StringTableEntry cwd = NULL;
if (!cwd)
{
char cwd_buf[2048];
GetCurrentDirectoryA(2047, cwd_buf);
forwardslash(cwd_buf);
cwd = StringTable->insert(cwd_buf);
}
return cwd;
}
[b]
StringTableEntry Platform::getUserDirectory()
{
static StringTableEntry userDir = NULL;
if (!userDir)
{
char buf[2048];
if (SHGetSpecialFolderPathA(NULL, buf, CSIDL_APPDATA, FALSE))
{
forwardslash(buf);
userDir = StringTable->insert(buf);
}
}
return userDir;
}
StringTableEntry Platform::getCommonUserDirectory()
{
static StringTableEntry coomonUserDir = NULL;
if (!coomonUserDir)
{
char buf[2048];
if (SHGetSpecialFolderPathA(NULL, buf, CSIDL_COMMON_APPDATA, FALSE))
{
forwardslash(buf);
coomonUserDir = StringTable->insert(buf);
}
}
return coomonUserDir;
}
[/b]------------------------------------------------------------------------------
File: platformWin32\platformWin32.h
Line: 21
#include <windows.h> [b]#include <shlobj.h>[/b] #ifndef _PLATFORM_H_
------------------------------------------------------------------------------
File: console\consoleFunctions.cc
Line: 1467
ConsoleFunction(getWorkingDirectory, const char *, 1, 1, "getWorkingDirectory()")
{
return Platform::getWorkingDirectory();
}
[b]
ConsoleFunction(getUserDirectory, const char *, 1, 1, "getUserDirectory()")
{
return Platform::getUserDirectory();
}
ConsoleFunction(getCommonUserDirectory, const char *, 1, 1, "getCommonUserDirectory()")
{
return Platform::getCommonUserDirectory();
}
[/b]Here's my testing from console log (Win XP SP2)
==>echo(getWorkingDirectory()); D:/Projects/Torque/tgb/game ==>echo(getUserDirectory()); C:/Documents and Settings/Kruzoe/Application Data ==>echo(getCommonUserDirectory()); C:/Documents and Settings/All Users/Application Data
Hope this helps.
#11
You should make a resource out of this, I'm sure other people are interested in this too. Maybe someone will step up and fill in the mac part.
If you want the 20$ bounty I put onto this, just mail me your paypal ID ;)
01/04/2007 (11:27 am)
Great! Works like a charm. Thanks a lot.You should make a resource out of this, I'm sure other people are interested in this too. Maybe someone will step up and fill in the mac part.
If you want the 20$ bounty I put onto this, just mail me your paypal ID ;)
#12
01/04/2007 (11:29 am)
Do you know what it will return on windows 95/98/ME ? What if this folder doesn't exist? Do I get an empty string returned? Don't have a win 98 system to test here :(
#13
01/04/2007 (1:00 pm)
Oh, and I just wanted to add this. Looks like you guys were right after all, I can't write text files using stock Torque file IO (unless you go outside of the mod folder by using a path like "../../myfile.txt", but using the xml console resource, i can write to the common application data folder. So I finally have it working now.
#14
So, I think It works fine on Windows 98 and above. On Windows 95 you may need to install Internet Explorer 4.0 or you can add shell32.dll to you root of your game directory (not sure for the second option).
If you want to let the functions create directory for you if it does not exist. Just change the boolean flags.
and
I didn't try to failed the function yet. But I think it will return an empty string for sure. May be other persons can try it with different situations and see what's happen.
About your bounty. No, You don't need to pay me I just want to help. But if you mind you can give me a copy of your game ;) j/k.
I have many things to learn and play with TGB and I think it may be useful for other people. I'm considering to make them as resources but I have to finish my project first. May be in a few months?
01/04/2007 (5:26 pm)
From MSDNQuote:
Minimum DLL Version: shell32.dll version 4.71 or later
Minimum operating systems: Windows 2000, Windows NT 4.0 with Internet Explorer 4.0, Windows 98, Windows 95 with Internet Explorer 4.0
So, I think It works fine on Windows 98 and above. On Windows 95 you may need to install Internet Explorer 4.0 or you can add shell32.dll to you root of your game directory (not sure for the second option).
If you want to let the functions create directory for you if it does not exist. Just change the boolean flags.
if (SHGetSpecialFolderPathA(NULL, buf, CSIDL_APPDATA, FALSE)) to if (SHGetSpecialFolderPathA(NULL, buf, CSIDL_APPDATA, [b]TRUE[/b]))
and
if (SHGetSpecialFolderPathA(NULL, buf, CSIDL_COMMON_APPDATA, FALSE)) to if (SHGetSpecialFolderPathA(NULL, buf, CSIDL_COMMON_APPDATA, [b]TRUE[/b]))
I didn't try to failed the function yet. But I think it will return an empty string for sure. May be other persons can try it with different situations and see what's happen.
About your bounty. No, You don't need to pay me I just want to help. But if you mind you can give me a copy of your game ;) j/k.
I have many things to learn and play with TGB and I think it may be useful for other people. I'm considering to make them as resources but I have to finish my project first. May be in a few months?
#15
That's against Microsoft's license agreements, don't do that unless you want to get sued.
T.
01/04/2007 (11:07 pm)
Quote:or you can add shell32.dll to you root of your game directory
That's against Microsoft's license agreements, don't do that unless you want to get sued.
T.
#16
01/05/2007 (12:07 am)
Quote:But if you mind you can give me a copy of your gameA free copy of my game it is. I'll send on next week (almost finished now).
#17
I didn't know about that. Thank you for the warning Tom.
Thank you, Ward. I wishes you success with your game.
01/05/2007 (1:10 am)
Quote:
That's against Microsoft's license agreements, don't do that unless you want to get sued.
I didn't know about that. Thank you for the warning Tom.
Quote:
A free copy of my game it is. I'll send on next week (almost finished now).
Thank you, Ward. I wishes you success with your game.
Torque Owner Very Interactive Person