We return the value that is set in the registry for the computer. If that value has been changed by an administrator, its possible that they have also set the directory to be write protected. It seems that the prudent thing to do is to check to see that the parent folderitem is not nil and IsWritable before trying to use it.
That’s bad advice. The Docs folder should only hold data that the user conciously puts in there, not data the app needs to put for its own workings.
More generally, the rule is:
Documents: User chooses to put data there (i.e. the may user nagivate to it).
ApplicationData: App puts data there that the user should never have to navigate to. This may be used for preference files as well we for global data file (e.g. database) that the app manages for the user without the user ever choosing to “open” or “save as” those files in there.
Preferences folder: This is very OS dependent. On OSX, no app should actually create or open files in it any more, but only use the OSX API functions to get or set individual preference values. On Win and Linux I am not sure, and Michael’s note is important in this regard, I think. For that reason, I would entirely avoid the Preferences folder and use the ApplicationData folder instead.
Note, though, that there may be differences between files + prefs shared by all users and those private to each individal users. I believe SpecialFolder offers “shared” variations for that purpose, even, or doesn’t it? Not having it ready to look at right now.
In the event that the application cannot both read and write to the folder returned by SpecialFolder.Preferences, I am experimenting with using a fallback routine which will call ExpandEnvironmentStringsW and use it to try to access the preferences folder (in the location it would usually be found in Windows):
declare function ExpandEnvironmentStringsW lib"kernel32.dll" (lpSrc as WString,lpDst as ptr,nSize as integer) as integer
dim ret_buf as new memoryBlock(10000)
dim ret_bytes as integer
if windows_xp then
if ret_bytes=0 then
dim path as string = ret_buf.WString(0)
dim ret_f as new FolderItem(path,FolderItem.PathTypeShell)