Page 1 of 1

Okay, where do you store your data.

Posted: Fri Dec 07, 2007 2:20 am
by Dare
Or perhaps the question should be "best practice" for data storage.

A little while ago I changed where my apps stored data, using some code provided by gnozal. I have been following a topic in OffTopic by DoubleDutch regarding an app. Which brought a question to mind.

What should go where?

Currently I use the "Documents and Settings\ [...] \Application Data\" folders with "company\appname\" appended.

If an app is for all users, then the [...] above is "All Users" otherwise it is "User Name".

However there are also "UserData" and "My Documents" folders available and some apps just skip "Application Data" etc and create their homes right under "Documents And Setting\User Name\" (or under "Documents And Setting\All Users\")

So now I am wondering which would be the best to use. What is the best practice? Most logical?

What do you do (or suggest)?


Also, as a side question, are folders like the "UserData" directory (Documents and Settings\User Name\UserData\) guaranteed to be there on a newly installed OS? I know "All Users\UserData" is not guaranteed as it is not on my box.

Posted: Fri Dec 07, 2007 5:06 am
by Rescator
My suggestion is X:\Documents and Settings\XXXX\Application Data\Companyname\Programname\

For stuff like config and other data that should survive roaming, but the user need not worry about directly.

X:\Documents and Settings\XXXX\Application Data\
is also what is known as the AppData folder,

use API functions to get it as I do seem to recall that XP and Vista use different locations.
There should be some nice code in the tips and tricks forum on those API calls.

Likewise, the My Documents folder should be used for storing user initiated saves, save games, and possibly settings or other files that the user may want to access directly for some reason.

By the sound of it though you seem to be doing it correctly, just make sure you use the API calls to get the paths.

... crap, we've talked about this before haven't we? *laughs*
http://www.purebasic.fr/english/viewtop ... 9&start=20

There are 4 procedures there, together they should provide you with all the standard locations for single user stuff. Whiping up some AllUsers variants where appropriate shouldn't be so hard.
Those should be pretty close to the styleguide for XP and Vista.

Posted: Fri Dec 07, 2007 9:26 am
by Dare
Hi,

I had forgotten about that post. Thanks for the jog. And the code! :)


With the storing of data (and judging by the way apps have done things on my comp) everybody seems to be doing their own thing. More or less.

I think I will stick with Application Data\XXXX\ and just check for certain files in the folders to see whether the data is all users or just the current user.



BTW:
Has anyone dealt with a situation where two or more people use the same box, with different logins. And install the same software, each for their own use.

I have not worked out how I am going to handle that possible scenario yet (in the installation process).

Posted: Fri Dec 07, 2007 10:55 am
by Fangbeast
API solutions are nice and are saved in my toolbox but..What's wrong with using PB internal commands to do the same thing??

From the manual:

Result$ = GetCurrentDirectory()
Result$ = GetHomeDirectory()
Result$ = GetTemporaryDirectory()

Posted: Fri Dec 07, 2007 1:03 pm
by Trond
None of those gets the application data directory, that's what's wrong with them.

Posted: Fri Dec 07, 2007 1:18 pm
by Fangbeast
So what? It's a start. The manual is always a good place to start to using cross platform solutions before running to the API.

I didn't say it was the whole answer.

More feature requests to the dev team I'd say.

Posted: Sat Dec 08, 2007 1:13 am
by Dare
Hi guys.

Thanks.


So ... where do you keep your app's user data (DBs and etc)?

Posted: Sat Dec 08, 2007 2:02 am
by Fangbeast
Dare wrote:Hi guys.

Thanks.


So ... where do you keep your app's user data (DBs and etc)?
I always use the same schema as Rescator showed above.

Posted: Sat Dec 08, 2007 4:13 am
by Rescator
Fangbeast wrote:API solutions are nice and are saved in my toolbox but..What's wrong with using PB internal commands to do the same thing??

From the manual:

Result$ = GetCurrentDirectory()
Result$ = GetHomeDirectory()
Result$ = GetTemporaryDirectory()
Well GetCurrentDirectory() is fine as it is.

GetTemporaryDirectory() is nice too but in my procedure it will also create it if it does not exist. (ensures that the temp folder is always available)
Can't recall why I did that but reading up on windows back then I do seem to recal that (probably older Win 9x or NT etc) did not have a temp folder by default?

And GetHomeDirectory() refers to the "Home" directory which is not the same as the appdata folder (who's name varies depending on language choice on a Windows system) On Linux the home directory is more consistent and less messy or?

Initially I made those procedures for my installer code.

It would be really cool if the PB Team added something similar to my procedures, but they are Windows specific, and they would have to stumble through a bunch of Windows documentation and articles to make sure it behaves consistently across all supported Windows versions, plus they don't really have a Linux equivalent ("My Documents" on Linux is the same as the home directory though, right?)

Of course the PB team could solve this by simply pointing the appdata and mydocuments etc to a subdirectory in the users home directory on Linux.
(or is that the someplace in the usr and cfg directories? *scratches head*)

And then there is the issue of the Mac platform.

But yeah as you said, it would be very nice to see these implemented into PB native functions as it would allow almost platform independent install and operation with no need to worry exactly where stuff is put as those functions would handle the mess for us. And as I posted those procedures with no license attached they are considered public domain so feel free to steal them Fred :P

Posted: Sat Dec 08, 2007 4:50 am
by Fangbeast
Good explanation Rescator.

Posted: Sat Dec 08, 2007 9:35 pm
by michaeled314

Code: Select all

listptr.l
String$ = Space(#MAX_PATH)
SIGetSpecialFolderLocation_(#CSIDL_COMMON_DOCUMENTS,@listptr)
SIGetPathFromIDList_(listptr,@String$)
Debug String$

Posted: Thu Dec 13, 2007 5:24 am
by Dare
Hi guys.

Thanks for the responses.

I have decided that I will use "USER\Application Data\" if it is there and if not then extend the program folder to hold data.

Hopefully this covers all situations (Vista & other MS OS)

I will ignore other folders like "My Documents" so data is in either the system Application Data folder or in the program folder's subfolder.


Any reason to not do it that way?


The following code is how I will decide:

Code: Select all

; gnozal's special folder routine.
Procedure.s SpecialFolder(SpecialFolder)
  Protected ListPtr.l, SpecialFolderPath.s
  SpecialFolderPath = Space(#MAX_PATH)
  If SHGetSpecialFolderLocation_(0, SpecialFolder, @ListPtr) = #NOERROR
    SHGetPathFromIDList_(ListPtr, @SpecialFolderPath)
  EndIf
  ProcedureReturn Trim(SpecialFolderPath)
EndProcedure

; ======================================================
; locateDataFolder(userInfo)

; Decide on a folder to store user data.
;
; Use the MS recommended folder if possible.
; If not, extend the program path to have a data folder
;
; If userInfo = 1, ALL USERS is the main path
; else the user name is the main path.
;
; Allows for an extension of up to three items into the
; folder name, eg Company, Suite and Application can be
; incorporated into the path name.
;

CompilerIf Defined(UNLEN, #PB_Constant)
CompilerElse
  #UNLEN = 256
CompilerEndIf

Procedure.s locateDataFolder(userInfo.l = 0, coy.s ="", suite.s = "", app.s = "")
  Protected dataPath.s
  Protected userName.s
  Protected extended.s
  Protected sz.l
  
  If coy <> ""
    extended + coy + "\"
  EndIf
  If suite <> ""
    extended + suite + "\"
  EndIf
  If app <> ""
    extended + app + "\"
  EndIf
  
  If userInfo = 1
    dataPath = specialfolder(#CSIDL_COMMON_APPDATA) + "\" + extended
  Else
    dataPath = specialfolder(#CSIDL_APPDATA) + "\" + extended
  EndIf
; dataPath = "\" + extended
  If dataPath = "\" + extended
    dataPath = GetPathPart(ProgramFilename())
    If userInfo = 1
      dataPath + "data\All Users\"
    Else
      sz = #UNLEN + 1
      userName = Space(sz)
      GetUserName_(@userName, @sz)
      If userName = ""
        userName = "[UNKNOWN]"
      EndIf
      dataPath + "data\" + userName + "\" + extended
    EndIf
  EndIf
  ProcedureReturn dataPath
EndProcedure

Debug locateDataFolder()
Debug locateDataFolder(1)
Debug locateDataFolder(0,"One")
Debug locateDataFolder(0,"One","Two")
Debug locateDataFolder(0,"One","Two","Three")
Hopefully it is the right way to do it.

Thanks again.