我有一个Delphi 6应用程序,像大多数Windows应用程序一样,将数据读取/写入用户的“本地应用程序数据”文件夹。 我使用下面的代码来确定该文件夹。 到目前为止,该代码为我的大多数用户工作。 我遇到了本地应用程序数据不在预期文件夹中的用户:
C:\Users\Bob\AppData\Roaming\
通常,本地应用程序数据文件夹parsing为:
C:\Documents and Settings\Bob\Application Data\
这个用户特殊情况的奇怪之处在于通常在HKEY_LOCAL_MACHINE中find的几个registry项实际上位于HKEY_CURRENT_USER中。 他们在Windows 7上运行。
缺乏一个更好的词,有没有办法让用户“真正”的应用程序数据,所以我可以更好地浏览这种情况? 如果是在CSIDL_APPDATA,CSIDL_COMMON_APPDATA和CSIDL_LOCAL_APPDATA特殊文件夹之间进行智能select,那么这样做的逻辑是什么? 正如您所看到的,我正在寻找一种通用function,无论用户正在运行的Windows版本或其特定的PCconfiguration如何,都可以find正确的应用程序数据文件夹。
我发现这个堆栈溢出post似乎有答案,但它使用.NET库中的函数,我正在使用Delphi 6.如果这个解决scheme回答我的问题,有人可以告诉我一个快速的方法来复制它在Delphi中:
我怎样才能得到当前用户的“应用程序数据”文件夹的path?
// Function to get the app data special folder. function GetAppdataFolder: string; begin Result := GetSpecialFolderLocation(CSIDL_APPDATA); end;
您链接到的.net代码使用与CSIDL_APPDATA
完全相同的CSIDL_APPDATA
。 所以你的代码已经和你链接的.net代码一样了。 并且这两个引用与FOLDERID_RoamingAppData
相同的位置。
看看FOLDERID_RoamingAppData
的文档。 它说:
默认路径%APPDATA%(%USERPROFILE%\ AppData \ Roaming) 旧版默认路径%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
。 在不了解有关设置的更多细节的情况下,很难评论您的问题。
你可以使用这个(一个包装)。 您需要将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,或在那里镜像。
如果是在CSIDL_APPDATA,CSIDL_COMMON_APPDATA和CSIDL_LOCAL_APPDATA特殊文件夹之间进行智能选择,那么这样做的逻辑是什么?
是的,这只是一个问题。 您的代码已按预期工作。
CSIDL_APPDATA
( FOLDERID_RoamingAppData
)用于调用线程当前用户帐户(可以模拟)在多台机器上访问的数据(hense“漫游”数据)。
CSIDL_LOCAL_APPDATA
( FOLDERID_LocalAppData
)用于只能在本地计算机上调用线程的当前用户帐户(hense“local”data)访问的数据。
CSIDL_COMMON_APPDATA
( FOLDERID_ProgramData
)适用于只能在本地计算机上访问的数据(不是“漫游”数据)。