¿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;
|