Где сохранить INI-файл в зависимости от компьютера (не пользователя) в Windows - PullRequest
5 голосов
/ 11 августа 2009

Мое приложение в настоящий момент хранит настройки в INI-файле в профиле текущего пользователя (C:\Documents and Settings\<CurrentUser>\Application Data\MyApplication\MySettings.ini в WinXP). Но я понял, что некоторые из этих настроек уникальны для машины, а не для пользователя, и поэтому хотят (на самом деле нужно) сохранить их в одном месте для всех пользователей.

Есть ли в Windows XP (и более поздняя версия) папка, в которой можно хранить независимые от пользователя настройки?

ПРИМЕЧАНИЕ: Я не хочу хранить их в той же папке, что и мое приложение, и не хочу хранить их в реестре.

Я заметил, что в папке "C: \ Documents and Settings \" есть папка "Все пользователи"? Должен ли я хранить там?

Бонусные баллы: Я с большей вероятностью награду ответ тем, кто также может рассказать мне, как вернуть этот путь из Windows в Delphi 7.

Ответы [ 2 ]

12 голосов
/ 11 августа 2009

Для XP Windows предоставляет SHGetFolderPath () для получения известного местоположения. CSIDL, который вы ищете: CSIDL_COMMON_APPDATA, описывается как:

Каталог файловой системы, который содержит данные приложения для всех пользователей. Типичный путь - "C:\Documents and Settings\All Users\Application Data". Эта папка используется для данных приложения, которые не зависят от пользователя. Например, приложение может хранить словарь проверки орфографии, базу данных картинок или файл журнала в папке CSIDL_COMMON_APPDATA. Эта информация не будет перемещаться и доступна всем, кто использует компьютер.

Для Vista и более поздних версий это было заменено на SHGetKnownFolderPath () , хотя SHGetFolderPath () по-прежнему доступен в качестве функции-оболочки для этого. Если вы используете настоящий вызов Vista, вы должны использовать FOLDERID_ProgramData вместо CSIDL_COMMON_APPDATA.

Эта ссылка здесь , кажется, показывает способ сделать это.

Кажется, это сводится к этому (относитесь к этому с осмотрительностью, я не очень хорошо знаю Delphi):

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;

На этой странице представлен список всех значений CSIDL_* и FOLDERID_*. Помните, что вы должны использовать эти функции и для пользовательских данных, а не для жестко заданных значений, таких как "C:\Documents and Settings\<CurrentUser>\Application Data\". Возможно, версии Windows на разных языках используют разные имена каталогов, или пользователи могут свободно перемещать свои области данных.

6 голосов
/ 01 сентября 2009

Я бы порекомендовал использовать открытый код JEDI Code Library для такого рода вещей.

В JclShell.pas вы найдете GetSpecialFolderLocation ()

YourDataFolder := GetSpecialFolderLocation(CSIDL_COMMON_APPDATA);

Это бесплатно, хорошо протестировано, работает со всеми версиями Windows, и его использование защитит вас от будущих изменений в Windows API.

...