Найти «истинную» папку данных приложения пользователя Windows?

У меня есть приложение Delphi 6, которое, как и большинство приложений Windows, читает / записывает данные для пользователя "данные локального приложения " папка. Я использую код ниже, чтобы определить эту папку. До сих пор этот код работал для большинства моих пользователей. Я столкнулся с пользователем, данные локального приложения которого не находятся в ожидаемой папке:

C:\Users\Bob\AppData\Roaming\

Обычно локальная папка данных приложения разрешается в:

C:\Documents and Settings\Bob\Application Data\

Что странного в этом пользователе?Особая ситуация заключается в том, что несколько ключей реестра, обычно находящихся в HKEY_LOCAL_MACHINE, фактически находятся в HKEY_CURRENT_USER. Они работают на Windows 7.

Из-за отсутствия лучшего слова, есть ли способ получить "правда" данные приложения для пользователя, чтобы я мог лучше ориентироваться в этой ситуации? Если оно'вопрос разумного выбора между специальными папками CSIDL_APPDATA, CSIDL_COMMON_APPDATA и CSIDL_LOCAL_APPDATA, какова логика для этого? Как вы можете сказать, яЯ ищу универсальную функцию, которая может выкорчевать правильную папку данных приложения независимо от версии Windows, которую использует пользователь, или конкретной конфигурации ПК.

Я нашел этот пост переполнения стека, который, кажется, имеет ответ, но он использует функцию из библиотеки .NET, и я использую Delphi 6. Если это решение отвечает на мой вопрос, может кто-нибудь сказать мне быстрый способ воспроизвести его в Delphi:

Как я могу получить путь текущего пользователя "Данные Приложения" папка?

// Function to get the app data special folder.
function GetAppdataFolder: string;
begin
   Result := GetSpecialFolderLocation(CSIDL_APPDATA);
end;
 cja26 мар. 2013 г., 12:47
Где находится GetSpecialFolderLocation? (Какой блок я должен добавить к моему предложению использования?)
 Robert Oschler07 окт. 2012 г., 22:34
@SertacAkyuz - оказалось, что настоящая причина проблемы заключалась в том, что пользователю нужно было установить мою программу с правами администратора, чего не происходит у большинства пользователей ».системы. Чтобы быть справедливым по отношению к тем, кто уже ответил на исходное сообщение, я вернул сообщение к исходному виду и создал новое сообщение для нового вопроса:stackoverflow.com/questions/12772615/...

Ответы на вопрос(3)

Решение Вопроса

Environment.SpecialFolder.ApplicationData что точно так же, какCSIDL_APPDATA, Таким образом, ваш код уже эквивалентен коду .net, на который вы ссылаетесь. И оба они относятся к тому же месту, что и.FOLDERID_RoamingAppData

Посмотрите на документацию дляFOLDERID_RoamingAppData, Это говорит:

Default Path        %APPDATA% (%USERPROFILE%\AppData\Roaming)
Legacy Default Path %APPDATA% (%USERPROFILE%\Application Data) 

"Путь по умолчанию " это то, что вы увидите на Vista или позже. "Legacy Path " это то, что вы видите на XP.

Различное поведение, которое вы наблюдали, является ничем иным, как ожидаемой разницей между XP и Vista / 7/8.

На моей машине с Windows,

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

оценивает

C:\Users\heff\AppData\Roaming

Другими словами, ваш код уже работает правильно. Вам не нужно вносить какие-либо изменения в него вообще. Продолжайте использовать.GetSpecialFolderLocation(CSIDL_APPDATA)

Что странного в этом пользователе?Особая ситуация заключается в том, что несколько ключей реестра, обычно находящихся в HKEY_LOCAL_MACHINE, фактически находятся в HKEY_CURRENT_USER.

Тот'не редкость. Довольно часто приложения настраивают параметры по умолчанию вHKLM а затем скопировать их вHKCU когда приложение запускается впервые. Не зная более подробной информации о настройках, о которых идет речьТрудно комментировать этот аспект вашего вопроса.

 Robert Oschler07 окт. 2012 г., 22:35
Я вернул свой пост в исходную форму, прежде чем я представил проблему прав администратора, как вы просили.
 Robert Oschler07 окт. 2012 г., 22:47
@SertacAkyuz - не проблема, и спасибо вам за это.
 Giel17 окт. 2012 г., 22:34
@ Давид: для справки: мы получаем отчеты о сбоях с компьютеров Vista / 7, где "ShGetFolderPath (0, CSIDL_APPDATA, 0, shgfp_Type_Current, Path) " на самом деле возвращаетсяC: \ Users \ heff \ Application Data " вместо "C: \ Users \ Яэфф \ AppData \ Roaming», Мы можем'не могу написать в эту папку, и наша программа вылетает из-за этого.
 Robert Oschler07 окт. 2012 г., 22:16
Спасибо. Пожалуйста, смотрите мое последнее обновление в оригинальном сообщении.
 Robert Oschler07 окт. 2012 г., 22:39
Это была просто простая ошибка. Я хотел принять ваш ответ изначально. Это'исправлено
 David Heffernan07 окт. 2012 г., 22:21
Я ответил на вопрос, который вы задали. Возможно, ваше обновление связано с UAC, которого нет в XP. Я думаю это'Нечестно полностью изменить вопрос таким образом. Я приложил много усилий в этом ответе. Я думаю, что вы должны отменить вопрос, принять ответ и задать новый вопрос. С множеством деталей, которых здесь нет.
 Robert Oschler07 окт. 2012 г., 22:44
@SertacAkyuz - понятно. Я случайно вырезал фрагмент кода, когда вырезал текст, который использовал для создания нового потока. Я вижу, как это сбивает с толку. Извини за это. Это'с восстановлен.
 Robert Oschler07 окт. 2012 г., 22:23
Конечно. Я'Я сделаю это сейчас и спасибо.
 Sertac Akyuz07 окт. 2012 г., 22:46
@ Роберт - Значит, это была ошибка .. ЯМне очень жаль, что я принял это в сознание. Я'Я забираю обратно свое голосование и через некоторое время удаляю все мои комментарии.
Решение Вопроса

вопрос разумного выбора между специальными папками CSIDL_APPDATA, CSIDL_COMMON_APPDATA и CSIDL_LOCAL_APPDATA, какова логика для этого?

Да, это просто вопрос. Ваш код уже работает, как ожидалось. (

CSIDL_APPDATAFOLDERID_RoamingAppData) для данных, которые доступны вызывающему потокутекущая учетная запись пользователя (которая может быть олицетворена) на нескольких машинах (hense "роуминг" данные). (

CSIDL_LOCAL_APPDATAFOLDERID_LocalAppData) для данных, которые доступны вызывающему потокутекущая учетная запись пользователя только на локальном компьютере (hense "местный" данные). (

CSIDL_COMMON_APPDATAFOLDERID_ProgramData) для данных, которые доступны для любой учетной записи пользователя только на локальном компьютере (не "роуминг" данные).

Вам нужно будет добавить ShlApi к вашему предложению использования. Пропусти этоCSIDL_APPDATA так же, как ваш образец выше. Для списка различныхCSIDL_ значения, см.Страница MSDN здесь

function GetShellFolder(CSIDLFolder : integer) : string;
begin
  SetLength(Result, MAX_PATH);
  SHGetSpecialFolderPath(0, PChar(Result), CSIDLFolder, false);
  SetLength(Result, StrLen(PChar(Result)));
  if (Result <> '') then
    Result  := IncludeTrailingBackslash(Result);
end;

Если ты'Поддерживая более раннюю версию Windows (XP и ниже), в которой вы видите текст, вы можете использоватьSHGetFolderPath вместо:

function GetFolderPath(Wnd: HWnd; CSIDLFolder: Integer): string;
begin
  SetLength(Result, MAX_PATH);
  Result := SHGetFolderPath(Wnd, CSIDLFolder, nil, 0, PChar(Result);
  SetLength(Result, StrLen(PChar(Result)));
end;

Если ты'Вы поддерживаете только Vista и выше, вы должны использоватьSHGetKnownFolderPath вместо этого, и передать его.KNOWNFOLDERID

Что касается проблемы с реестром, Windows Vista и 7 гораздо более ограничительны в отношении мест, в которые пользователь, не являющийся администратором, может писать, и одно из мест, где это происходит, - это HKLM и HKCR. Многие из предметов, которые раньше были в этих ульях, теперь находятся в HKCU или отражены там.

 Ken White07 окт. 2012 г., 21:05
Я думаю, мыя увижу. :-)
 David Heffernan07 окт. 2012 г., 20:56
Я прочитал код в вопросе как код, который используется в настоящее время. А потомссылки наCSIDL_COMMON_APPDATA а такжеCSIDL_LOCAL_APPDATA, Роберт спрашивает, что использовать. По крайней мере, этокак я это читаю Я думаю, что Роберт используетGetSpecialFolderLocation из библиотеки JEDI. Я думаю, что Роберт использует машину XP и неРаспознать реорганизацию папок профиля, которые MS сделала в Vista. Он считает, что разные пути указывают на нечто большее.
 Robert Oschler07 окт. 2012 г., 22:17
@KenWhite. Спасибо. Пожалуйста, смотрите мое последнее обновление в оригинальном сообщении.
 David Heffernan07 окт. 2012 г., 20:51
Isn»т вопрос о которомCSIDL использовать, а не как преобразовать это в путь? Мне кажется, что Роберт уже знает, как преобразоватьCSIDL в путь. Или я читаю это неправильно?
 Ken White07 окт. 2012 г., 20:55
Я думаю ты'читаете это неправильно. Его текст, кажется, указывает на то, что онне читает путь (онПредполагает местоположение), и, следовательно, возникают проблемы с пользователем на Win7, где данные находятся в неправильном месте. Он говорит, что онне в состоянии использовать решение, которое он нашел, потому что этос .NET и онс помощью Delphi.

Ваш ответ на вопрос