我有一个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版本或其特定PC配置的正确应用程序数据文件夹的通用功能。
我发现这个Stack Overflow帖子似乎有答案但是它使用的是.NET库中的函数而我正在使用Delphi 6.如果这个解决方案回答了我的问题,有人能告诉我一个快速的方法来复制它Delphi的:
How can i get the path of the current user's "Application Data" folder?
// Function to get the app data special folder.
function GetAppdataFolder: string;
begin
Result := GetSpecialFolderLocation(CSIDL_APPDATA);
end;
答案 0 :(得分:8)
您链接到的.net代码使用的Environment.SpecialFolder.ApplicationData
与CSIDL_APPDATA
完全相同。因此,您的代码已经等同于您链接的.net代码。这些都指向与FOLDERID_RoamingAppData
相同的位置。
查看FOLDERID_RoamingAppData
的文档。它说:
Default Path %APPDATA% (%USERPROFILE%\AppData\Roaming) Legacy Default Path %APPDATA% (%USERPROFILE%\Application Data)
您将在Vista或更高版本中看到“默认路径”。 “传统路径”就是你在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
。如果不了解有关设置的更多详细信息,则很难对您问题的这一方面发表评论。
答案 1 :(得分:5)
你可以使用它(一个包装器)。您需要将ShlApi添加到您的uses子句中。像上面的示例一样传递CSIDL_APPDATA
。有关各种CSIDL_
值的列表,请参阅MSDN page here
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,或者在那里被反映出来。
答案 2 :(得分:5)
如果是在CSIDL_APPDATA,CSIDL_COMMON_APPDATA和CSIDL_LOCAL_APPDATA特殊文件夹之间进行智能选择,那么这样做的逻辑是什么?
是的,这只是一个问题。您的代码已按预期工作。
CSIDL_APPDATA
(FOLDERID_RoamingAppData
)用于在多台计算机上调用线程的当前用户帐户(可以模拟)访问的数据(hense“漫游”数据)。
CSIDL_LOCAL_APPDATA
(FOLDERID_LocalAppData
)用于仅在本地计算机上调用线程的当前用户帐户可访问的数据(hense“local”数据)。
CSIDL_COMMON_APPDATA
(FOLDERID_ProgramData
)仅适用于本地计算机上任何用户帐户可访问的数据(不是“漫游”数据)。