2012-10-07 39 views
10

我有一个Delphi 6应用程序,像大多数Windows应用程序一样,将数据读取/写入用户的“本地应用程序数据”文件夹。我使用下面的代码来确定该文件夹。到目前为止,该代码适用于大多数用户。我也遇到过,其本地应用程序数据不在预期的文件夹中的用户:查找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配置。

我发现这个堆栈溢出帖子似乎有答案,但它使用.NET库中的函数,我使用的是Delphi 6.如果这个解决方案回答我的问题,有人可以告诉我一个快速的方法来复制它德尔福:

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

@SertacAkyuz - 事实证明,问题的真正原因是用户需要使用管理员权限来安装我的程序,这在大多数用户的系统上不会发生。为了公平对那些已经回复原帖的人,我将帖子恢复为原始形式,并为这个新问题创建了一个新帖子:http://stackoverflow.com/questions/12772615/why-is-my-delphi -6-program-triggering-a-request-for-admin-rights-upon-install-on –

+0

GetSpecialFolderLocation在哪里? (我应该将哪个单元添加到我的使用条款中?) – cja

回答

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。在不了解有关设置的更多细节的情况下,很难对您的问题的这一方面发表评论。

+0

谢谢。请在原始帖子中查看我最近的更新。 –

+0

我回答了你问的问题。您的更新可能与XP上不存在的UAC有关。我认为完全改变这个问题是不公平的。我在这个答案中付出了很多努力。我认为你应该回避这个问题,接受答案并提出一个新问题。有很多细节不在这里。 –

+0

当然。我现在要做,谢谢你。 –

5

你可以使用这个(包装)。您需要将ShlApi添加到您的使用条款中。就像你上面的样品一样,通过它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中,或者在那里被镜像。

+0

是不是有关使用哪个'CSIDL'而不是如何将其转换为路径的问题?它看起来好像罗伯特已经知道如何将CSIDL转换成路径。还是我读错了? –

+0

我认为你读的不正确。他的文本似乎表明他没有阅读路径(他正在推测位置),因此在Win7上遇到数据出错地点的用户时遇到问题。他说他*不能*使用他找到的解决方案,因为它来自.NET,而他正在使用Delphi。 –

+0

我将问题中的代码读为当前正在使用的代码。然后是对“CSIDL_COMMON_APPDATA”和“CSIDL_LOCAL_APPDATA”的引用。罗伯特正在问哪个使用。至少我是这样读的。我认为Robert正在使用JEDI库中的'GetSpecialFolderLocation'。我认为罗伯特正在使用XP机器,并且无法识别MS在Vista中制作的配置文件文件夹的重新组织。他认为不同的途径表明的不仅仅是这些。 –

5

如果它的CSIDL_APPDATA,CSIDL_COMMON_APPDATA和CSIDL_LOCAL_APPDATA特殊文件夹之间选择智能的事,什么是这样做的逻辑是什么?

是的,这只是一个问题。您的代码已按预期工作。

CSIDL_APPDATAFOLDERID_RoamingAppData)适用于多个机器(hense“漫游”数据)上的调用线程当前用户帐户(可以模拟)访问的数据。

CSIDL_LOCAL_APPDATAFOLDERID_LocalAppData)适用于只能在本地计算机上调用线程的当前用户帐户(hense“local”data)访问的数据。

CSIDL_COMMON_APPDATAFOLDERID_ProgramData)适用于仅供本地计算机上的任何用户帐户(而非“漫游”数据)访问的数据。

相关问题