2012-10-07 11 views
10

Ho un'applicazione Delphi 6 che, come la maggior parte delle applicazioni Windows, legge/scrive i dati nella cartella "dati dell'applicazione locale" dell'utente. Io uso il codice qui sotto per determinare quella cartella. Fino ad ora, quel codice funzionava per la maggior parte dei miei utenti. Ho incontrato un utente il cui locale Dati applicazioni non è nella cartella atteso:Trovare la cartella dati "vera" di un utente Windows?

C:\Users\Bob\AppData\Roaming\ 

Di solito la cartella dei dati applicazione locale di delibera di:

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

Ciò che è strano in particolare la situazione di questo utente è che molti le chiavi di registro normalmente presenti in HKEY_LOCAL_MACHINE si trovano in HKEY_CURRENT_USER. Esse sono in esecuzione su Windows 7.

Per mancanza di una parola migliore, c'è un modo per ottenere i dati dell'applicazione "veri" per un utente in modo da poter navigare meglio in questa situazione? Se si tratta di scegliere in modo intelligente tra le cartelle speciali CSIDL_APPDATA, CSIDL_COMMON_APPDATA e CSIDL_LOCAL_APPDATA, qual è la logica per farlo? Come puoi vedere, sto cercando una funzione per tutti gli usi che possa estirpare la cartella dati dell'applicazione corretta indipendentemente dalla versione di Windows in esecuzione o dalla specifica configurazione del PC.

Ho trovato questo post di Overflow dello stack che sembra avere la risposta ma utilizza la funzione dalla libreria .NET e sto usando Delphi 6. Se questa soluzione risponde alla mia domanda, qualcuno può dirmi un modo rapido per replicarlo a Delfi:

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 - si è scoperto che la vera causa del problema era che l'utente aveva bisogno di installare il mio programma con diritti di amministrazione, cosa che non accade sulla maggior parte dei sistemi dell'utente. Per essere onesti con coloro che avevano già risposto al post originale, ho ripristinato il post nel modulo originale e creato un nuovo post per la nuova domanda: http://stackoverflow.com/questions/12772615/why-is-my-delphi -6-program-triggering-a-request-per-admin-rights-on-install-on –

+0

Dove si trova GetSpecialFolderLocation? (Quale unità dovrei aggiungere alla mia clausola sugli usi?) – cja

risposta

8

Il codice .net che si collega a utilizza Environment.SpecialFolder.ApplicationData che è esattamente la stessa di CSIDL_APPDATA. Quindi il tuo codice è già equivalente al codice .net a cui ti colleghi. E entrambi si riferiscono alla stessa posizione di FOLDERID_RoamingAppData.

Dai un'occhiata alla documentazione di FOLDERID_RoamingAppData. Dice:

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

Il "Percorso predefinito" è ciò che vedrete in Vista o successivo. Il "Percorso Legacy" è ciò che vedi su XP.

Il diverso comportamento che si è osservato non è altro che la differenza prevista tra XP e Vista/7/8.

Sulla mia macchina Windows,

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 

viene valutato come

C:\Users\heff\AppData\Roaming 

In altre parole, il codice sta già facendo la cosa giusta. Non è necessario apportare alcuna modifica ad esso. Continuare a utilizzare GetSpecialFolderLocation(CSIDL_APPDATA).


Qual è strano in particolare la situazione di questo utente è che diverse chiavi di registro che normalmente si trovano in HKEY_LOCAL_MACHINE sono in realtà si trova in HKEY_CURRENT_USER.

Questo non è raro. Molto spesso le applicazioni configurano le impostazioni predefinite in HKLM e quindi le copiano in HKCU quando l'applicazione viene eseguita per la prima volta. Senza conoscere più dettagli delle impostazioni in questione è difficile commentare questo aspetto della tua domanda.

+0

Grazie. Si prega di consultare il mio recente aggiornamento nel post originale. –

+0

Ho risposto alla domanda che hai chiesto. Il tuo aggiornamento è forse correlato a UAC che non è presente su XP. Penso che non sia giusto cambiare completamente la domanda in questo modo. Ho fatto un grande sforzo in questa risposta. Penso che dovresti ripristinare la domanda, accettare la risposta e fare una nuova domanda. Con molti dettagli che non sono qui. –

+0

Ovviamente. Lo farò adesso e grazie. –

5

È possibile utilizzare questo (un wrapper). Dovrai aggiungere ShlApi alla tua clausola sugli usi. Passa allo CSIDL_APPDATA proprio come fa il tuo esempio sopra. Per un elenco dei vari valori CSIDL_, vedere la 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; 

Se si sta sostenendo precedente di Windows (XP e sotto), che il testo appare è il caso, è possibile utilizzare SHGetFolderPath invece:

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; 

Se si supporta solo Vista e versioni successive, utilizzare invece SHGetKnownFolderPath e passarlo a KNOWNFOLDERID.

Per quanto riguarda il problema del Registro di sistema, Windows Vista e 7 sono molto più restrittivi sui luoghi in cui un utente non amministratore può scrivere e uno dei posti che si verifica è in HKLM e HKCR. Molti degli oggetti che erano in quegli alveari sono ora in HKCU, o sono specchiati lì.

+0

Non è la domanda su quale 'CSIDL' usare piuttosto che come convertirlo in un percorso? Mi sembra che Robert sappia già come convertire un CSIDL in un percorso. O lo sto leggendo in modo errato? –

+0

Penso che tu stia leggendo in modo errato. Il suo testo sembra indicare che non sta leggendo il percorso (presumerà la posizione), e quindi sta avendo problemi con un utente su Win7 in cui i dati sono nel posto sbagliato. Dice che è * incapace * di usare la soluzione trovata perché è di .NET e sta usando Delphi. –

+0

Ho letto il codice nella domanda come il codice attualmente in uso. E poi ci sono i riferimenti a 'CSIDL_COMMON_APPDATA' e' CSIDL_LOCAL_APPDATA'. Robert sta chiedendo quale usare. Almeno è così che l'ho letto. Penso che Robert stia usando 'GetSpecialFolderLocation' dalla libreria JEDI. Penso che Robert stia usando una macchina XP e non riconosca la riorganizzazione delle cartelle dei profili create da MS in Vista. Pensa che i diversi percorsi indicano qualcosa di più. –

5

Se si tratta di una questione di intelligenza scegliere tra le CSIDL_APPDATA, CSIDL_COMMON_APPDATA e CSIDL_LOCAL_APPDATA cartelle speciali, qual è la logica per farlo?

Sì, è solo una questione di questo. Il tuo codice funziona già come previsto.

CSIDL_APPDATA (FOLDERID_RoamingAppData) è per dati accessibili per l'account utente corrente del thread chiamante (che può essere rappresentato) su più computer (dati "di roaming" elevati).

CSIDL_LOCAL_APPDATA (FOLDERID_LocalAppData) è per dati accessibili per l'account utente corrente del thread chiamante solo sulla macchina locale (dati "locali" concisi).

CSIDL_COMMON_APPDATA (FOLDERID_ProgramData) è per dati accessibili a qualsiasi account utente solo sulla macchina locale (non dati di "roaming").

Problemi correlati