SHGetFolderPath не работает для меня - PullRequest
3 голосов
/ 25 ноября 2011

У меня есть эта функция:

function GetProfilePath: string;
const
  SHGFP_TYPE_CURRENT = 0;
var
  hToken: THandle;
  ProfilePath: packed array[ 0..MAX_PATH ] of Char;
begin
  ZeroMemory(@ProfilePath[0], SizeOf(ProfilePath));
  OpenProcessToken( GetCurrentProcess, TOKEN_QUERY, hToken );
  SHGetFolderPath( 0, CSIDL_APPDATA, hToken , SHGFP_TYPE_CURRENT, @ProfilePath[ 0 ] );
  CloseHandle( hToken );
  Result := ProfilePath;
end;

SHGetFolderPath возвращает E_FAIL (0x80004005) и пустой буфер ProfilePath. MSDN говорит, что E_FAIL означает «CSIDL в nFolder действителен, но папка не существует». Но папка существует, я уверен. Когда я создаю простое тестовое приложение и запускаю тот же код, он работает хорошо.

Что может быть не так с этим?

обновление : Я обнаружил, что мое приложение не работает хорошо при работе под Delphi. Когда я запускаю его отдельно, все в порядке.

Спасибо, Roman

1 Ответ

2 голосов
/ 25 ноября 2011

Использование пользовательского токена выглядит излишне сложным. Но, сказав это, когда я запустил ваш код на моей машине, он работал без ошибок. Возможно, пользовательский токен для вашего процесса не имеет достаточных прав на эту папку. Или, возможно, папка действительно не существует!

Я думаю, вам стоит использовать более простой API SHGetSpecialFolderPath. Моя обертка для этого выглядит так:

function GetSpecialFolderPath(const CSIDL: Integer): string;
var
  Buffer: TWin32PathBuffer;
begin
  if SHGetSpecialFolderPath(Application.Handle, @Buffer[0], CSIDL, False) then begin
    Result := Buffer;
  end else begin
    RaiseLastOSError;
  end;
end;

Конечно, это может дать сбой точно так же, как ваша версия, если папка действительно не существует.


ОК, я только что перечитал этот комментарий в вашем вопросе:

Когда я создаю простое тестовое приложение и запускаю тот же код, он хорошо работает.

Звучит так, будто вы запускаете настоящий код в другом контексте. Возможно в сервисе? Или с олицетворением пользователя. Может быть, это ключ к решению этой проблемы. Что вы не говорите нам о среде / контексте / настройке, где код не работает?


И некоторые очень незначительные комментарии к вашему коду. Вы определили ProfilePath с еще одним элементом, чем необходимо, и packed является избыточным для массива:

ProfilePath: array[ 0..MAX_PATH-1 ] of Char;

Или, что еще лучше, повторно использовать тип, определенный в Delphi RTL, TWin32PathBuffer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...