2012-10-07 38 views
10

Tengo una aplicación Delphi 6 que, como la mayoría de las aplicaciones de Windows, lee/escribe datos en la carpeta de "datos de la aplicación local" del usuario. Uso el código a continuación para determinar esa carpeta. Hasta ahora, ese código funcionaba para la mayoría de mis usuarios. He encontrado un usuario cuyo local de aplicación de datos no está en la carpeta esperada:Encontrar la carpeta de datos de la aplicación "verdadera" de un usuario de Windows?

C:\Users\Bob\AppData\Roaming\ 

Por lo general, la carpeta de datos de aplicación local declara que:

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

Lo que es raro en la situación particular de este usuario es que varios las claves de registro que normalmente se encuentran en HKEY_LOCAL_MACHINE en realidad se encuentran en HKEY_CURRENT_USER. Se están ejecutando en Windows 7.

Por falta de una palabra mejor, ¿hay alguna forma de obtener los datos de aplicación "verdaderos" para un usuario para poder navegar mejor en esta situación? Si se trata de elegir inteligentemente entre las carpetas especiales CSIDL_APPDATA, CSIDL_COMMON_APPDATA y CSIDL_LOCAL_APPDATA, ¿cuál es la lógica para hacerlo? Como puede ver, estoy buscando una función multiuso que pueda eliminar la carpeta de datos de la aplicación correcta independientemente de la versión de Windows que esté ejecutando el usuario o la configuración específica de su PC.

Encontré esta publicación de Stack Overflow que parece tener la respuesta pero está usando la función de la biblioteca .NET y estoy usando Delphi 6. Si esta solución responde mi pregunta, ¿alguien me puede decir una forma rápida de replicarlo? en 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 - Resultó que la verdadera causa del problema era que el usuario necesitaba instalar mi programa con derechos de administrador, algo que no ocurre en la mayoría de los sistemas del usuario. Para ser justos con aquellos que ya habían respondido la publicación original, revertí la publicación al formulario original y creé una nueva publicación para la nueva pregunta: http://stackoverflow.com/questions/12772615/why-is-my-delphi -6-program-triggering-a-request-for-admin-rights-upon-install-on –

+0

¿Dónde está GetSpecialFolderLocation? (¿Qué unidad debo agregar a mi cláusula uses?) – cja

Respuesta

8

El código .net al que se vincula utiliza Environment.SpecialFolder.ApplicationData, que es exactamente lo mismo que CSIDL_APPDATA. Entonces su código ya es equivalente al código .net al que se vincula. Y ambos se refieren a la misma ubicación que FOLDERID_RoamingAppData.

Eche un vistazo a la documentación para FOLDERID_RoamingAppData. Dice:

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

La "ruta de acceso predeterminada" es lo que verá en Vista o posterior. El "Camino heredado" es lo que ves en XP.

El comportamiento diferente que ha observado no es más que la diferencia esperada entre XP y Vista/7/8.

En mi máquina de Windows,

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 

evalúa a

C:\Users\heff\AppData\Roaming 

En otras palabras, el código ya está haciendo lo correcto. No necesita hacer ningún cambio en absoluto. Continuar usando GetSpecialFolderLocation(CSIDL_APPDATA).


Lo que es raro en la situación particular de este usuario es que varias claves de registro que normalmente se encuentran en HKEY_LOCAL_MACHINE están situados realmente en HKEY_CURRENT_USER.

Eso no es raro. Muy a menudo las aplicaciones configuran las configuraciones predeterminadas en HKLM y luego las copian a HKCU cuando la aplicación se ejecuta por primera vez. Sin saber más detalles sobre la configuración en cuestión, es difícil comentar ese aspecto de su pregunta.

+0

Gracias. Por favor, mira mi actualización reciente en la publicación original. –

+0

Respondí la pregunta que hizo. Su actualización quizás esté relacionada con UAC que no está presente en XP. Creo que no es justo cambiar por completo la pregunta de esta manera. Puse mucho esfuerzo en esta respuesta. Creo que debes revertir la pregunta, aceptar la respuesta y hacer una nueva pregunta. Con muchos detalles que no están aquí. –

+0

Por supuesto. Haré eso ahora y gracias. –

5

puede utilizar esta (una envoltura). Deberá agregar ShlApi a su cláusula de uso. Páselo CSIDL_APPDATA como lo hace su muestra de arriba. Para obtener una lista de los distintos valores de CSIDL_, ver el 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; 

Si usted está apoyando anterior de Windows (XP y abajo), el cual aparece el texto es el caso, se puede utilizar en lugar 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; 

Si solo está admitiendo Vista y versiones superiores, debe usar SHGetKnownFolderPath en su lugar, y pasarlo a KNOWNFOLDERID.

En cuanto al problema del registro, Windows Vista y 7 son mucho más restrictivos sobre los lugares en los que un usuario no administrador puede escribir, y uno de los lugares que ocurre es en HKLM y HKCR. Muchos de los artículos que solían estar en esas colmenas ahora están en HKCU, o están reflejados allí.

+0

¿No se trata de qué 'CSIDL' usar en lugar de cómo convertir eso en una ruta? Me parece que Robert ya sabe cómo convertir un 'CSIDL' en una ruta. ¿O lo estoy leyendo incorrectamente? –

+0

Creo que lo estás leyendo incorrectamente. Su texto parece indicar que no está leyendo el camino (está presumiendo la ubicación), y por lo tanto está teniendo problemas con un usuario en Win7 donde los datos están en el lugar equivocado. Él dice que * no puede * usar la solución que encontró porque es de .NET y está usando Delphi. –

+0

Leí el código en la pregunta como el código que se está utilizando actualmente. Y luego están las referencias a 'CSIDL_COMMON_APPDATA' y' CSIDL_LOCAL_APPDATA'. Robert pregunta qué usar. Al menos así es como lo leí. Creo que Robert está usando 'GetSpecialFolderLocation' de la biblioteca JEDI. Creo que Robert está usando una máquina de XP y no reconoce la reorganización de las carpetas de perfil que MS hizo en Vista. Él piensa que las diferentes rutas indican algo más que eso. –

5

Si se trata de una cuestión de elegir inteligentemente entre las carpetas especiales CSIDL_APPDATA, CSIDL_COMMON_APPDATA y CSIDL_LOCAL_APPDATA, ¿cuál es la lógica para hacerlo?

Sí, es solo cuestión de eso. Tu código ya está funcionando como se esperaba.

CSIDL_APPDATA (FOLDERID_RoamingAppData) es para los datos a los que se puede acceder desde la cuenta de usuario actual del subproceso que realiza la llamada (que puede suplantarse) en varias máquinas (en los datos de "roaming").

CSIDL_LOCAL_APPDATA (FOLDERID_LocalAppData) es para los datos a los que se puede acceder desde la cuenta de usuario actual del subproceso que realiza la llamada en la máquina local solamente (en los datos "locales").

CSIDL_COMMON_APPDATA (FOLDERID_ProgramData) es para los datos a los que se puede acceder desde cualquier cuenta de usuario en la máquina local solamente (no en los datos de "roaming").

Cuestiones relacionadas