full - delphi versiones
¿Cómo puedo automatizar la obtención de la fecha de creación en una constante visible para mi código? (7)
Cualquier versión de Delphi, solo Windows batch para crear un archivo .inc antes de compilar. No se necesita IDE en absoluto.
Aquí el guión:
REM CommandInterpreter: $(COMSPEC)
@echo off
setlocal enabledelayedexpansion
setlocal
rem determine project top level directory from command file name
set PRJDIR=%~dp0
cd %PRJDIR%
set BUILD_DATE_FILE=%PRJDIR%Source/BuildDate.inc
call :GetGurrentDateTime&set BUILD_YEAR=!current_year!&set BUILD_MONTH=!current_month!&set BUILD_DAY=!current_day!&set BUILD_TIME=!current_time!
echo const BUILD_YEAR = %BUILD_YEAR%;> "%BUILD_DATE_FILE%"
:: 3 letter name Apr for April
echo const BUILD_MONTH = ''%BUILD_MONTH%'';>> "%BUILD_DATE_FILE%"
echo const BUILD_DAY = %BUILD_DAY%;>> "%BUILD_DATE_FILE%"
echo const BUILD_TIME = ''%BUILD_TIME%'';>> "%BUILD_DATE_FILE%"
goto :EOF
echo Done
exit /b 0
:GetGurrentDateTime
rem GET CURRENT DATE
echo.>"%TEMP%/~.ddf"
makecab /D RptFileName="%TEMP%/~.rpt" /D InfFileName="%TEMP%/~.inf" -f "%TEMP%/~.ddf">nul
for /f "tokens=4,5,6,7" %%a in (''type "%TEMP%/~.rpt"'') do (
if not defined current_date (
set "current_date=%%d-%%a-%%b"
set "current_time=%%c"
set "current_year=%%d"
set "current_month=%%a"
set "current_day=%%b"
)
)
En el código fuente solo incluya el archivo BuildDate.inc y use consts BUILD_*
.
Me gustaría definir en mi código una constante que contenga la fecha en la que se construyó el ejecutable. Naturalmente me gustaría automatizar ese proceso.
Sé que puedo escribir una secuencia de comandos previa a la compilación utilizando, por ejemplo, Perl, para escribir un archivo .inc
que contenga la fecha. Preferiría una solución más liviana utilizando, tal vez, variables de entorno o variables de compilación. ¿Proporciona msbuild alguna variable que ayude? ¿Alguien sabe una solución más ordenada para el problema?
De hecho, TCompile no es una unidad de Delphi. Lo puedes encontrar aquí, en EDN . Y (sólo una copia de la página):
Componente no visual que modifica el archivo unitario "Project.pas". Este archivo tiene la fecha y la hora en que se compiló el proyecto junto con el número de compilación. Coloque este componente en el TForm y luego configure la ruta del proyecto. Esto se puede hacer colocando el símbolo de intercalación en el campo de propiedad ProjectPath, luego presionando la tecla ENTRAR.
Incluir "Proyecto" en la cláusula USES; Guarde el proyecto, luego salga de Delphi. La próxima vez que se abra el proyecto en Delphi, se creará el archivo de la unidad "Project.pas". Luego, cada vez que ejecute el programa desde Delphi, el archivo de la unidad se actualizará con la fecha, la hora y el número de compilación actuales.
Este código funciona en las nuevas versiones de Delphi, combina la obtención de la hora y la conversión a la hora local.
function GetExeBuildTime: TDateTime;
var
LI: TLoadedImage;
{$IF CompilerVersion >= 26.0}
m: TMarshaller;
{$IFEND}
timeStamp: Cardinal;
utcTime: TDateTime;
begin
{$IF CompilerVersion >= 26.0} //XE7 requires TMarshaller to convert to PAnsiChar
Win32Check(MapAndLoad(PAnsiChar(m.AsAnsi(ParamStr(0)).ToPointer), nil, @LI, False, True));
{$ELSE}
Win32Check(MapAndLoad(PAnsiChar(AnsiString(ParamStr(0))), nil, @LI, False, True));
{$IFEND}
timeStamp := LI.FileHeader.FileHeader.TimeDateStamp;
UnMapAndLoad(@LI);
utcTime := UnixToDateTime(timeStamp);
Result := TTimeZone.Local.ToLocalTime(utcTime);
end;
Puede leer la marca de tiempo del vinculador desde el encabezado PE del ejecutable:
uses
ImageHlp;
function LinkerTimeStamp(const FileName: string): TDateTime; overload;
var
LI: TLoadedImage;
begin
Win32Check(MapAndLoad(PChar(FileName), nil, @LI, False, True));
Result := LI.FileHeader.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta;
UnMapAndLoad(@LI);
end;
Para la imagen cargada del módulo actual, lo siguiente parece funcionar:
function LinkerTimestamp: TDateTime; overload;
begin
Result := PImageNtHeaders(HInstance + Cardinal(PImageDosHeader(HInstance)^._lfanew))^.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta;
end;
Las versiones anteriores de Delphi no se actualizaron correctamente, pero se corrigieron alrededor de Delphi 2010 o algo así. Para las versiones anteriores, usé un complemento IDE para actualizarlo automáticamente después de una compilación exitosa.
Nota: el valor se almacena como UTC, por lo que, para fines de visualización, es posible que deba convertirlo en una zona horaria adecuada.
Si usa / tiene JCL , jclPEImage.PeReadLinkerTimeStamp()
hace lo que está buscando. Las versiones anteriores de Delphi no establecieron la marca de tiempo del vinculador, pero sí las nuevas versiones de AFAIK (es decir, parece funcionar bien con D2010).
Utilizo FinalBuilder para hacer todas mis compilaciones, y con eso es fácil agregar una utilidad que actualizará cualquier archivo de origen antes de la compilación para buscar y modificar la definición de una variable o constante. Construyo números de versión, fechas, cualquier cosa que tenga sentido de esta manera.
DDevExtensions tiene una opción para incluir la fecha y la hora de compilación en el recurso versioninfo. Supongo que no tengo que mostrarte cómo extraer eso desde dentro del programa ...
Actualización sobre compilaciones automatizadas: FinalBuilder tiene una opción similar.