Best place for user data files (vista and before)

Just starting out? Need help? Post your questions and find answers here.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

srod wrote:I'm probably being a little dense here! :)

But why does Appdata.s = GetEnvironmentVariable("%appdata%") just produce an empty string on my system?
Mine too. Vista Business.

cheers
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

But why does Appdata.s = GetEnvironmentVariable("%appdata%") just produce an empty string on my system?
Maybe that environment variable isn't set by some(thing)one ? isn't sHGetSpecialFolderLocation() with a #CSIDL_ the best or
recomended way to get to these locations?
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Yes, I would never use environment variables because they are subject to change.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
freak
PureBasic Team
PureBasic Team
Posts: 5948
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

It should be GetEnvironmentVariable("APPDATA"). The % is only for replacement in batch files/the command shell.
I would recommend the code from gnozal. Its only requirement is IE4 which
should be available on all systems except maybe the very early Win95 releases.

Also you should be descriptive in the foldernames you create there so users can
find the application's data for backup purposes.
A MD5 is not such a good idea imho. It is pretty easy today to verify with search engines
if some other software product uses the same program name, and as Trond said,
if you unclude the company name you can be pretty certain that there is no conflict.
quidquid Latine dictum sit altum videtur
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

Hi guys.

Thanks for all the help and feedback. Very much appreciated.

I will use :

Code: Select all

dataPath.s = SpecialFolder(#CSIDL_COMMON_APPDATA) + "\" + myBusinessName.s + "\" + myAppName.s + "\"
unless OSVersion() advises 95. If 95 or if SpecialFolder fails (via SHGetSpecialFolderLocation_(..) <> #S_OK or SHGetPathFromIDList_(..) <> #True) for some reason (eg missing IE) then I will default to the approach I currently use. And if that fails, tough. :)

You guys are winners. Thanks again.
Dare2 cut down to size
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

You might find these pretty useful.

Code: Select all

Procedure.s GetKeyValue(topKey.l,sKey$,sValue$)
 Protected lType.l,lpcbData.l,hKey.l,lpData$,path$
 lpData$=Space(2048+1)
 lpcbData=Len(lpData$)-1
 If RegOpenKeyEx_(topKey,sKey$,#Null,#KEY_READ,@hKey)=#ERROR_SUCCESS
  RegQueryValueEx_(hKey,sValue$,#Null,@lType,@lpData$,@lpcbData)
  RegCloseKey_(hKey)
 EndIf
 ProcedureReturn Trim(lpData$)
EndProcedure

Procedure.s SpecialFolderLocation(csidl.l)
 Protected location$,pidl.l
 If SHGetSpecialFolderLocation_(#Null,csidl,@pidl)=#ERROR_SUCCESS
  location$=Space(#MAX_PATH)
  If SHGetPathFromIDList_(pidl,@location$)
   If Right(location$,1)<>"\"
    location$+"\"
   EndIf
  EndIf
  If pidl
   CoTaskMemFree_(pidl) ;Instead of messing with com imalloc free and whatnot.
  EndIf
 EndIf
 ProcedureReturn Trim(location$)
EndProcedure

Procedure.s GetProgramFilesDir()
 Protected os.l,value$,path$
 os=OSVersion()
 If os>#PB_OS_Windows_ME
  path$=SpecialFolderLocation(#CSIDL_PROGRAM_FILES)
 Else
  value$=GetKeyValue(#HKEY_LOCAL_MACHINE,"Software\Microsoft\Windows\Currentversion","ProgramFilesDir")
  If value$<>""
   path$=value$
   If Right(value$,1)<>"\"
    path$+"\"
   EndIf
  EndIf
 EndIf
 If FileSize(path$)<>-2
  If CreateDirectory(path$)=#False
   path$=""
  EndIf
 EndIf
 ProcedureReturn path$
EndProcedure

Procedure.s GetApplicationDataDirectory()
 Protected path$
 path$=SpecialFolderLocation(#CSIDL_APPDATA)
 If path$="" ;Needed since Windows 95 do not support CSIDL_APPDATA "out of the box".
  path$=GetProgramFilesDir()+"Application Data\"
 EndIf
 If FileSize(path$)<>-2
  If CreateDirectory(path$)=#False
   path$=""
  EndIf
 EndIf
 ProcedureReturn path$
EndProcedure

Procedure.s GetMyDocumentsDirectory()
 Protected path$
 path$=SpecialFolderLocation(#CSIDL_PERSONAL) ;My Documents\ folder, use this rather than the other CSIDL
 If FileSize(path$)<>-2
  If CreateDirectory(path$)=#False
   path$=""
  EndIf
 EndIf
 ProcedureReturn path$
EndProcedure

Procedure.s GetTempDirectory()
 Protected path$,pathlen.l,result.l
 path$=Space(2048+1)
 result=GetTempPath_(Len(path$)-1,@path$)
 If (result=0) Or (result>Len(path$))
  path$=""
 Else
  If Right(path$,1)<>"\"
   path$+"\"
  EndIf
  If FileSize(path$)<>-2
   If CreateDirectory(path$)=#False
    path$=""
   EndIf
  EndIf
 EndIf
 ProcedureReturn path$
EndProcedure
GetProgramFilesDir() ;For example C:\Program Files\
Typically the default install location for programs.
Make sure to use \Company\Appname\ as a common courtesy.

GetApplicationDataDirectory() ;For example C:\Documents and Settings\username\Application Data\
The advised place to put program settings and such files.
Make sure to do the nice \Company\Appname\ thing here too :)

GetMyDocumentsDirectory() ;For example C:\Documents and Settings\username\My Documents\
The advised place to put documents, game save files, etc.
Make sure to do the nice \Company\Appname\ thing here too :)

GetTempDirectory() ;For example C:\Documents and Settings\username\Local Settings\Temp\
The advised place to put temporary files.
Make sure the filename is pretty unique or you make a folder that you put the temp files in, and always cleanup after yourself so you don't bloat the temp folder.
Last edited by Rescator on Tue Aug 07, 2007 12:00 am, edited 1 time in total.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Hehe, well, and here is how I did it for my prog:

Code: Select all

Procedure.s GetSpecialFolderPath(CSIDL.l)
  Protected *itemid.ITEMIDLIST, location.s = Space(#MAX_PATH)
  If SHGetSpecialFolderLocation_(0,CSIDL,@*itemid) = #NOERROR
    If SHGetPathFromIDList_(*itemid,@location)
      ProcedureReturn location
    EndIf
  EndIf
EndProcedure

Global AppdataPath$ = GetSpecialFolderPath(#CSIDL_APPDATA)
Global ProgramPath$ = GetPathPart(ProgramFilename())

If Not ProgramParameter(0) = "/portable" And FileSize("portable.txt") = -1
  If Not FileSize(AppdataPath$+"\JLC's Software")=-2
    CreateDirectory(AppdataPath$+"\JLC's Software")
  EndIf
  If Not FileSize(AppdataPath$+"\JLC's Software\Radio Player")=-2
    CreateDirectory(AppdataPath$+"\JLC's Software\Radio Player")
  EndIf
  SetCurrentDirectory(AppdataPath$+"\JLC's Software\Radio Player")
EndIf
And whenever is important for something to be saved in the same path as the executable use the ProgramPath$ variable. But for me, I didn't need to. Note how the user can easily change it into "portable" mode also.
I like logic, hence I dislike humans but love computers.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Joakim you got a memory leak,
please compare my SpecialFolderLocation() with your GetSpecialFolderPath()
PSDK/MSDN wrote:A pointer to an item identifier list (PIDL) specifying the folder's location relative to the root of the namespace (the desktop). The calling application is responsible for freeing this pointer
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

Hi guys.

Thanks! Will look at these procedures in a few days. (Not being rude, just bogged down with the final stages of a business takeover and just about everything else is on the backburner at the moment).
Dare2 cut down to size
Post Reply