问题
My application is currently storing settings in an INI file under the current user's profile ( C:\Documents and Settings\<CurrentUser>\Application Data\MyApplication\MySettings.ini under WinXP). But I've realised some of these settings are unique to the machine not the user and thus want (actually need) to save them in a single location for all users.
Is there a folder location on Windows XP (and up) where I can store user independent settings?
NOTE: I don't want to store them in the same folder as my application nor do I want to store them in the registry.
I notice there is an "All Users" folder under "C:\Documents and Settings\"? Should I be storing under there?
Bonus Points: I'm more likely to award the answer to whoever can also tell me how to return this path from Windows in Delphi 7.
回答1:
For XP, Windows provides SHGetFolderPath() to get a known location. The CSIDL that you're looking for is CSIDL_COMMON_APPDATA, described as:
The file system directory that contains application data for all users. A typical path is
"C:\Documents and Settings\All Users\Application Data". This folder is used for application data that is not user specific. For example, an application can store a spell-check dictionary, a database of clip art, or a log file in theCSIDL_COMMON_APPDATAfolder. This information will not roam and is available to anyone using the computer.
For Vista and later, this has been replaced with SHGetKnownFolderPath() although SHGetFolderPath() is still available as a wrapper function for that. If you use the real Vista call, you should use FOLDERID_ProgramData instead of CSIDL_COMMON_APPDATA.
This link here seems to show a way of doing it.
It seems to boil down to this (treat this with circumspection, I don't know Delphi that well):
function ShGetKnownFolderPath (
const rfid: TGUID;
dwFlags: DWord;
hToken: THandle;
out ppszPath: PWideChar): HResult;
var
Shell: HModule;
Fn: TShGetKnownFolderPath;
begin
Shell := LoadLibrary ('shell32.dll');
Win32Check(Shell <> 0);
try
@Fn := GetProcAddress (Shell, 'SHGetKnownFolderPath');
Win32Check (Assigned (Fn));
Result := Fn (rfid, dwFlags, hToken, ppszPath);
finally
FreeLibrary (Shell);
end;
end;
function GetKnownFolderPath (
const rfid: TGUID;
dwFlags: DWord;
hToken: THandle): WideString;
var
buffer: PWideChar;
ret: HResult;
begin
ret :=ShGetKnownFolderPath (rfid, dwFlags, hToken, buffer);
OleCheck (ret);
try
Result := buffer;
finally
CoTaskMemFree (buffer);
end;
end;
This page provides a list of all the CSIDL_* and FOLDERID_* values. Keep in mind you should be using these functions for your user-specific data as well, not hard-coded values like "C:\Documents and Settings\<CurrentUser>\Application Data\". It may be that different language versions of Windows use different directory names or it's possible that users can freely move their data areas around.
回答2:
I'd recommend using the open source JEDI Code Library for this sort of thing.
In JclShell.pas you'll find GetSpecialFolderLocation()
YourDataFolder := GetSpecialFolderLocation(CSIDL_COMMON_APPDATA);
It's free, well tested, works with all Windows versions and using it will insulate you from future changes to the Windows API.
来源:https://stackoverflow.com/questions/1258146/where-to-save-ini-file-dependent-to-machine-not-user-on-windows