2012-10-07 10 views
10

Mam aplikację Delphi 6, która, podobnie jak większość aplikacji systemu Windows, odczytuje/zapisuje dane w folderze "lokalne dane aplikacji" użytkownika. Używam poniższego kodu, aby określić ten folder. Do tej pory ten kod działał dla większości moich użytkowników. Mam napotkał użytkownika, którego lokalna aplikacja danych nie jest w oczekiwanym folderze:Znajdowanie "prawdziwego" folderu danych aplikacji użytkownika systemu Windows?

C:\Users\Bob\AppData\Roaming\ 

Zazwyczaj folder app dane lokalne postanawia:

C:\Documents and Settings\Bob\Application Data\ 

Co jest dziwnego w konkretnej sytuacji tego użytkownika jest, że kilka klucze rejestru zwykle znalezione w HKEY_LOCAL_MACHINE znajdują się w HKEY_CURRENT_USER. Działają w systemie Windows 7.

Z braku lepszego słowa, czy istnieje sposób na uzyskanie "prawdziwych" danych aplikacji dla użytkownika, aby lepiej poradzić sobie z tą sytuacją? Jeśli chodzi o inteligentny wybór między specjalnymi folderami CSIDL_APPDATA, CSIDL_COMMON_APPDATA i CSIDL_LOCAL_APPDATA, jaka jest logika tego działania? Jak można się przekonać, szukam funkcji uniwersalnej, która może wykorzenić poprawny folder danych aplikacji, niezależnie od wersji systemu Windows, z której korzysta użytkownik, lub od konfiguracji komputera.

Znalazłem ten post przepełnienia stosu, który wydaje się mieć odpowiedź, ale używa funkcji z biblioteki .NET i używam Delphi 6. Jeśli to rozwiązanie odpowiada na moje pytanie, czy ktoś może mi szybko podać kopię tego pytania 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

@SertacAkyuz - okazało się, że prawdziwą przyczyną problemu było to, że użytkownik musiał zainstalować mój program z uprawnieniami administratora, co nie dzieje się na większości systemów użytkownika. Aby być uczciwym wobec tych, którzy już odpowiedzieli na oryginalny post, cofnąłem wpis do pierwotnego formularza i utworzyłem nowy wpis dla nowego pytania: http://stackoverflow.com/questions/12772615/why-is-my-delphi -6-program-wyzwalanie-a-żądanie-dla-administratora-uprawnień-po instalacji- –

+0

Gdzie jest GetSpecialFolderLocation? (Którą jednostkę należy dodać do mojej klauzuli zastosowania?) – cja

Odpowiedz

8

Kod .net, który łączysz, używa Environment.SpecialFolder.ApplicationData, który jest dokładnie taki sam jak CSIDL_APPDATA. Twój kod jest już równoważny z kodem .net, z którym łączysz. Oba odnoszą się do tej samej lokalizacji co FOLDERID_RoamingAppData.

Zapoznaj się z dokumentacją dla FOLDERID_RoamingAppData. Jest napisane:

 
Default Path  %APPDATA% (%USERPROFILE%\AppData\Roaming) 
Legacy Default Path %APPDATA% (%USERPROFILE%\Application Data) 

"Domyślna ścieżka" jest taka, jak w Vista lub później. "Wcześniejsza ścieżka" jest tym, co widzisz na XP.

Różne zaobserwowane zachowanie jest niczym więcej niż oczekiwaną różnicą między XP a Vista/7/8.

Na moim komputerze z systemem Windows,

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 

ocenia się

C:\Users\heff\AppData\Roaming 

Innymi słowy, Twój kod jest już robi słusznie. Nie musisz wprowadzać w nim żadnych zmian. Kontynuuj używanie GetSpecialFolderLocation(CSIDL_APPDATA).


Co jest dziwnego w konkretnej sytuacji tego użytkownika jest, że kilka kluczy rejestru normalnie znalezione w kluczu HKEY_LOCAL_MACHINE są w rzeczywistości znajduje się w kluczu HKEY_CURRENT_USER.

To nie jest rzadkie. Dość często aplikacje konfigurują domyślne ustawienia w HKLM, a następnie kopiują je do HKCU, gdy aplikacja jest uruchamiana po raz pierwszy. Bez znajomości szczegółów tych ustawień trudno jest skomentować ten aspekt Twojego pytania.

+0

Dziękuję. Zobacz moją ostatnią aktualizację w oryginalnym wpisie. –

+0

Odpowiedziałem na zadane pytanie. Twoja aktualizacja jest prawdopodobnie związana z UAC, którego nie ma na XP. Myślę, że to nie w porządku, aby całkowicie zmienić takie pytanie. Wkładam w to wiele wysiłku. Myślę, że powinieneś odwrócić pytanie, zaakceptować odpowiedź i zadać nowe pytanie. Mnóstwo szczegółów, których tu nie ma. –

+0

Oczywiście. Zrobię to teraz i dziękuję. –

5

można użyć tego (owijki). Będziesz musiał dodać ShlApi do swojej klauzuli uses. Przekaż to CSIDL_APPDATA, tak jak twój przykład powyżej. Aby uzyskać listę różnych wartościach CSIDL_, zobacz 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; 

Jeśli wspieranie wcześniej systemu Windows XP (i poniżej), który pojawia się tekst jest, można użyć zamiast 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; 

Jeśli obsługujesz tylko wersję Vista i wyższą, powinieneś zamiast tego użyć SHGetKnownFolderPath i przekazać ją KNOWNFOLDERID.

Jeśli chodzi o problem z rejestrem, systemy Windows Vista i 7 są znacznie bardziej restrykcyjne w miejscach, w których można pisać bez uprawnień administratora, a jedno z miejsc występuje w HKLM i HKCR. Wiele przedmiotów, które kiedyś znajdowały się w tych ulu, znajduje się teraz w HKCU lub jest tam odzwierciedlone.

+0

Nie jest pytanie, który "CSIDL" należy użyć, a nie jak przekonwertować go na ścieżkę? Wydaje mi się, że Robert już wie, jak przekonwertować 'CSIDL' na ścieżkę. Czy czytam go niepoprawnie? –

+0

Myślę, że czytasz to niepoprawnie. Jego tekst zdaje się wskazywać, że nie czyta ścieżki (zakłada lokalizację) i dlatego ma problem z użytkownikiem na Win7, gdzie dane znajdują się w niewłaściwym miejscu. Mówi, że nie jest w stanie * użyć rozwiązania, które znalazł, ponieważ pochodzi z platformy .NET i używa Delphi. –

+0

Przeczytałem kod w pytaniu jako kod, który jest aktualnie używany. A potem są odniesienia do 'CSIDL_COMMON_APPDATA' i' CSIDL_LOCAL_APPDATA'. Robert pyta, którego użyć. Przynajmniej tak to czytam. Myślę, że Robert używa 'GetSpecialFolderLocation' z biblioteki JEDI. Sądzę, że Robert używa maszyny XP i nie rozpoznaje reorganizacji folderów profili utworzonych przez MS w Vista. Uważa, że ​​różne ścieżki wskazują na coś więcej. –

5

Jeśli jest to kwestia inteligentnie wybiera pomiędzy specjalnymi folderami CSIDL_APPDATA, CSIDL_COMMON_APPDATA i CSIDL_LOCAL_APPDATA, jaka jest logika takiego postępowania?

Tak, to tylko kwestia tego. Twój kod działa już zgodnie z oczekiwaniami.

CSIDL_APPDATA (FOLDERID_RoamingAppData) jest dla danych, które są dostępne dla bieżącego konta użytkownika wątku wywołującego (pod którym można podszywać się) na wielu komputerach (hense dane "roaming").

CSIDL_LOCAL_APPDATA ((FOLDERID_LocalAppData) jest dla danych, które są dostępne dla bieżącego konta użytkownika wątku wywołującego tylko na komputerze lokalnym (hense "lokalne" dane).

CSIDL_COMMON_APPDATA (FOLDERID_ProgramData) dla danych dostępnych dla dowolnego konta użytkownika tylko na komputerze lokalnym (dane nie "roamingowe").

Powiązane problemy