2010-08-09 40 views
6

Estoy usando Delphi 2010 y mi programa quiere obtener la ruta temporal del sistema. Estoy usando TPath.GetTempPath y todo está funcionando bien ... al menos para mí y mis compañeros de trabajo. Pero en algunas máquinas de clientes, este método devuelve una ruta recortada que (por supuesto) no existe. Descubrí que el problema parece ser el resultado de una llamada subyacente a GetLongPathName().Delphi TPath.GetTempPath resultado se recorta

El código completo es el siguiente:

[...] 
var 
TmpDir : String; 
Len : Integer; 
begin 

[... Call to GetTempPath succeeds and we have a valid temp directory in short "~" notation in var TmpDir ...] 

Len := GetLongPathName(PChar(TmpDir), nil, 0);  // Len = 37 
    SetLength(TmpDir, Len - 1);       // We want to set the len of TmpDir to 37 - 1. 
    GetLongPathName(PChar(TmpDir), PChar(TmpDir), Len); // Only 32 (instead of 36) characters are copied - so we have a cropped path - But why?! 

end; 
[...] 

Esto sólo ocurre en algunos sistemas y no sé qué. Encontré una solución desagradable para esto, pero me gustaría saber qué está pasando aquí.

¿Alguien puede aclarar esto?

+0

¿Puede darnos ejemplos de los nombres de ruta correctos (esperados) y malos (reales)? ¿Podría ser un problema de codificación Unicode? –

+0

Pensamos que también en primer lugar, pero los nombres de las rutas no contienen ningún carácter que pueda causar problemas con las conversiones Unicode. El nombre de ruta del resultado de GetLongPathName solo falta los últimos 4 caracteres ("emp \" de "Temp \") - todos los demás caracteres son válidos. – Patrick

+0

Suena como http://qc.embarcadero.com/wc/qcmain.aspx?d=92006 –

Respuesta

4

Hay una nota sobre esta función de API de Windows en las páginas de Seguridad Nacional:

"El búfer de cambio de GetLongPathName() y similares funciones puede devolver un ruta truncada y dar lugar a difíciles -buscar errores ".

https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/753-BSI.html

Si tiene el código fuente, se puede comprobar si el problema descrito en este artículo existe en la aplicación Delphi 2010.

+0

Tiene razón, eso también lo encontré y mi "solución desagradable" es establecer Len en MAX_PATH inicialmente y verificar el resultado de GetLongPathName(), pero me pregunto por qué Embarcadero está usando el otro enfoque ... pero gracias por publicar esto, porque verificó mi enfoque. – Patrick

+0

Debe informar esto al control de calidad. –

+1

¿Cuál es el problema? El código en la pregunta llama correctamente a la función dos veces, ¿no? Una vez para averiguar la longitud requerida y luego una segunda vez para llenar el búfer de verdad. El código que cita asigna el búfer primero para que la primera llamada a la función funcione, pero si falla, asigna un nuevo búfer y lo utiliza en su lugar. ¿Es realmente una diferencia importante? El artículo advierte contra asumir que la primera llamada siempre tendrá éxito cuando se le dé un búfer del tamaño MAX_PATH. ¿Cómo se aplica esa advertencia a esta situación? –

3

¿Qué ocurre si se intenta:

var 
    longpath : string; 

SetLength(longpath,MAX_PATH); 
SetLength(longpath, GetLongPathName(PChar(TmpDir),PChar(LongPath),MAX_PATH)); 

Esto funcionó para mí, su versión truncada de la ruta.

+0

Eso es lo que estoy haciendo en mi "solución alternativa": si el problema ocurre en su máquina: sería interesante si la función TPath.GetTempPath() funciona para usted. – Patrick

+1

Este código puede dejarle una cadena que es más larga que Max_Path, pero con solo caracteres Max_Path asignados. Es decir, 'Length (longpath)> StrLen (PChar (longpath))'. También podría quedarle una cadena con basura: los documentos no dicen qué almacena la función en el búfer cuando el búfer es demasiado pequeño. El boletín de seguridad y la documentación describen la forma de evitar ese problema. –

+0

Bien, deberíamos mencionar aquí, que el valor de retorno de GetLongPathName es importante y debe ser verificado. – Patrick

Cuestiones relacionadas