Page 2 of 2

Posted: Tue Jul 31, 2007 6:47 pm
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

Posted: Tue Jul 31, 2007 9:56 pm
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?

Posted: Tue Jul 31, 2007 9:59 pm
by PB
Yes, I would never use environment variables because they are subject to change.

Posted: Tue Jul 31, 2007 11:22 pm
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.

Posted: Wed Aug 01, 2007 2:13 am
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.

Posted: Mon Aug 06, 2007 11:34 pm
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.

Posted: Mon Aug 06, 2007 11:56 pm
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.

Posted: Tue Aug 07, 2007 12:04 am
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

Posted: Tue Aug 07, 2007 1:43 pm
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).