Использование пользовательского токена выглядит излишне сложным. Но, сказав это, когда я запустил ваш код на моей машине, он работал без ошибок. Возможно, пользовательский токен для вашего процесса не имеет достаточных прав на эту папку. Или, возможно, папка действительно не существует!
Я думаю, вам стоит использовать более простой 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
.