1

I'm building an image thumbnail cache system, and one of the main things I need it to do is basically ask Windows for the best place to store my permanent cached files. I've seen many good ways of getting temp directories, but I need a permanent cache location. How do I get this from Windows?

NOTE

This system will actually be working as a Windows Service (or a thread) running in the background - as well as many applications reading from this cache. It needs to be on a global level, and not per windows user.

Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
  • 2
    The local app data path? [`FOLDERID_LocalAppData`](http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx) – Andreas Rejbrand Jan 22 '12 at 00:20
  • Good source btw, I'm looking to see if there's one that isn't specific to users, because it will be global... – Jerry Dodge Jan 22 '12 at 00:23
  • @AndreasRejbrand Wait, that link says that these are compatible with Vista and above - would it work in XP at all? – Jerry Dodge Jan 22 '12 at 00:39
  • 2
    No, for XP compatibility you need to use the old [CSIDL classification](http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494(v=vs.85).aspx) instead. This works on Vista and 7 too, so use this unless you are deliberately targeting only Vista+. – Andreas Rejbrand Jan 22 '12 at 00:42
  • So then use `CSIDL_PROGRAM_FILES` right? – Jerry Dodge Jan 22 '12 at 00:44
  • 3
    I don't think it is appropriate to store data in the Program Files folder. `CSIDL_COMMON_APPDATA` is better. – Andreas Rejbrand Jan 22 '12 at 00:45
  • Perfect. Now how to get this in Delphi? – Jerry Dodge Jan 22 '12 at 00:47
  • Jerry: Just use the `SHGetFolderPath` function. – Andreas Rejbrand Jan 22 '12 at 00:48
  • What is an image cache? How will this be different from the images living in a folder? – David Heffernan Jan 22 '12 at 14:17
  • The original images are stored on the server, sometimes even over the internet. My cache system I'm building automatically keeps a local Thumbnail copy, usually no larger than 400x400. I'm providing user option of overriding cache directory, but need a default directory for when one isn't specified. – Jerry Dodge Jan 22 '12 at 18:51
  • If only there were a way I could ask Windows to *decide* which HDD is best fit for storing the cache - based on HDD space availability... – Jerry Dodge Jan 22 '12 at 18:53

2 Answers2

9

First you need to find out where to store your data. At MSDN is a list of the old CSIDL constants. To obtain a path from a CSIDL constant, use the SHGetFolderPath function like this (uses ShFolder):

procedure TForm1.Button1Click(Sender: TObject);
var
  path: array[0..MAX_PATH] of char;
begin
  SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, SHGFP_TYPE_CURRENT, @path);
  ShowMessage(path);
end;
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • 1
    CSIDL_COMMON_APPDATA needs write permissions for standard users. you might consider CSIDL_COMMON_DOCUMENTS if standard users will be modifying the cache files. – kobik Jan 22 '12 at 10:30
  • +1 for CSIDL_COMMON_DOCUMENTS. This is where I put 'global' stuff. Usually, I create a folder there using the EXE name. – Martin James Jan 22 '12 at 12:51
  • 2
    Well, I am not quite as fond of that idea. In my world, the common documents folder (as well as a per-user document folder) is a folder that the user is in charge of. Personally, I always get 'pissed off' when software adds stuff to my documents folder. That's my personal folder! (And, really, image cache files are not 'documents', especially not to the user.) – Andreas Rejbrand Jan 22 '12 at 12:53
  • @Andreas, I hear you, but you do not have much choice. I believe that MS twisted the whole concept regarding `CSIDL_COMMON_APPDATA`. If you want ALL users to be able to modify data in that folder (`CSIDL_COMMON_APPDATA\My Company\My App`) you need to implicitly add `modify` permission to `Users` group (in your setup program). I have seen many known application installing itself to "My Documents" as per user, and "My Shared Documents" for all users in UAC enabled OS. – kobik Jan 22 '12 at 14:28
  • 1
    @Andreas, your suggestion "local app data" (`CSIDL_LOCAL_APPDATA`) would have been my choice also for storing cache files. but since that OP accepted `CSIDL_COMMON_APPDATA` I suggested `CSIDL_COMMON_DOCUMENTS` as an alternative. – kobik Jan 22 '12 at 14:44
  • @kobik Actually Andreas' answer was open to any choice of folder constant. The code was an example use of such a constant. – Jerry Dodge Jan 22 '12 at 19:08
  • @JerryDodge, You wrote "I'm looking to see if there's one that isn't specific to users"... hens `CSIDL_COMMON_APPDATA` I suppose. I just pointed out the limitation with it. – kobik Jan 22 '12 at 19:18
  • Understood. Just pointing out the answer was open to using any constant. – Jerry Dodge Jan 22 '12 at 19:25
0

GetEnvironmentVariable(PATH_NAME)

PATH_NAME may be system name (WINDIR, TEMP, TMP etc.), but may be user defined path

indapublic
  • 2,208
  • 9
  • 38
  • 49