2012-10-07 44 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)適用於僅供本地計算機上的任何用戶帳戶(而非「漫遊」數據)訪問的數據。

相關問題