Página principal
Artículos y trucos
Catálogo de productos
Ejemplos y descargas
Mis libros
Cursos de formación
Investigación y desarrollo
Libros recomendados
Mis páginas favoritas
Acerca del autor
 
En colaboración con Amazon
 
Intuitive Sight

¿Dónde estoy?

¿Ha necesitado alguna vez conocer en qué directorio se está ejecutando su aplicación? Es muy fácil averiguarlo, sobre todo si la aplicación es un fichero ejecutable. Se trata de un truco que se remonta a los tiempos del venerable Turbo Pascal: hay que preguntar por el parámetro cero de la línea de comandos.

function TForm1.DirectorioAplicacion: string;
begin
  Result := ExtractFilePath(ParamStr(0));
end;

Suponiendo que lo que realmente deseo es el directorio desde donde se ejecuta el fichero, he utilizado la función ExtractFilePath, que se encuentra en la unidad SysUtils. Esta función deja la última barra de directorio al final del resultado.

Claro, los tiempos cambian, y las técnicas mejoran. En una aplicación escrita en Delphi para la interfaz gráfica de Windows es preferible utilizar la propiedad ExeName del objeto global Application:

function TForm1.DirectorioAplicacion: string;
begin
  Result := ExtractFilePath(Application.ExeName);
end;

Ahora bien, ¿qué pasa si lo que estamos escribiendo es una DLL, y queremos saber en qué directorio la han instalado, para saber desde dónde se está ejecutando? Está claro que ya no vale utilizar la lista de parámetros, y que el objeto global Application ya no nos sirve. En una aplicación CGI/ISAPI para Internet, incluso, el objeto Application no tiene nada que ver con el tradicionalmente definido en la unidad Forms.

Por suerte existe una función del API de Windows, GetModuleFileName, que nos va a sacar las castañas del fuego. ¿Qué tal si primero muestro una versión incorrecta del código necesario?

// Potencialmente incorrecta ...
function TForm1.DirectorioAplicacion: string;
var
  Buffer: array [0..255] of Char;
begin
  GetModuleFileName(0, Buffer, SizeOf(Buffer));
  Result := ExtractFilePath(StrPas(Buffer));
end;

Se trata de un error muy fácil de cometer, aunque difícil de detectar. ¿Se ha dado cuenta de que he pasado un cero en el primer parámetro de la función? Es que ese parámetro espera la instancia: un valor numérico que identifica unívocamente al programa...

...y ese es el problema. El valor cero corresponde al programa activo. Si estamos desarrollando un ejecutable, cero es perfectamente adecuado. Pero si la llamada se efectúa desde una DLL nuestra, ¡el directorio devuelto es el del ejecutable que llama a la DLL! Pero basta con utilizar la poco conocida variable global HInstance para que todo vuelva a la normalidad:

// Versión correcta
function TForm1.DirectorioAplicacion: string;
var
  Buffer: array [0..255] of Char;
begin
  GetModuleFileName(HInstance, Buffer, SizeOf(Buffer));
  Result := ExtractFilePath(StrPas(Buffer));
end;