Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Insertar y obtener la fecha de build. (https://www.clubdelphi.com/foros/showthread.php?t=65520)

Lord Delfos 21-12-2009 20:24:59

Insertar y obtener la fecha de build.
 
Buenas gente.

Esto es algo que ya deben haber preguntado cuarenta mil veces, pero no he encontrado nada al respecto.

Lo que me gustaría hacer es, de alguna manera AUTOMÁTICA, meter en el .EXE la fecha de buildeo. Así en la ventana de Acerca De yo puedo mostrar la versión exacta (ya sé cómo hacer eso) y la fecha de la última compilación.

¿Alguna idea? ¿URL? ¿Consejo? Lo que sea...

Miles de gracias.

Saludongos.

afunez2007 21-12-2009 21:53:04

Yo lo hago con esta funcion:

Código Delphi [-]
function GetFileDate(TheFileName: string): Double;
var
 FHandle: integer;
begin
 FHandle := FileOpen(TheFileName, 0);
 try
   Result := FileDateToDateTime(FileGetDate(FHandle));
 finally
   FileClose(FHandle);
 end;
end;

y para usarlo utilizas esto:
Código Delphi [-]
procedure TForm1.BitBtn1Click(Sender: TObject);
var fecha1:TDateTime;
begin
fecha1:= GetFileDate(ExtractFilePath(Application.ExeName)+'TuApp.exe');
end;

Lord Delfos 21-12-2009 22:51:49

Gracias, afunez2007.

Lo que pasa con este método tuyo es que si la fecha de archivo llega a cambiar (cosa que puede pasar con mucha facilidad) entonces mi ejecutable va a mostrar una fecha incorrecta.

Pos eso me interesa algún método que "grabe a fuego" en mi ejecutable la fecha y la hora de compilación.

Pero gracias de todos modos.

Neftali [Germán.Estévez] 22-12-2009 12:43:36

Hay tres fechas que se guardan en el archivo, la de creación, la de última modificación y la del último acceso.
Podrías utilizar la primera, de forma que si el archivo se modifica, cambiará la segunda, pero no la primera.

Aquí en mi página tienes un truco de cómo obtener esas tres fechas;
Fechas de un fichero (creación, modificación y últ. acceso)

Casimiro Notevi 22-12-2009 18:41:15

Yo uso esto, por si acaso te sirve:

Código:

lbVersion.Caption := 'v'+GetmVersion+
'-'+DateToStr(FileDateToDateTime(FileAge(paramStr(0))));



// -------------------------------------
function GetmVersion: string;
var
  InfoSize, H, RsltLen: Cardinal;
  VersionBlock: Pointer;
  Rslt: PVSFixedFileInfo;
begin
  InfoSize := GetFileVersionInfoSize(PChar(Application.ExeName), H);
  VersionBlock := AllocMem(InfoSize);
  try
    GetFileVersionInfo(PChar(Application.ExeName), H, InfoSize, VersionBlock);
    VerQueryValue(VersionBlock, '\', Pointer(Rslt), RsltLen);
    Result := Format('%d.%d.%d.%d', [
    Rslt.dwProductVersionMS div 65536,
    Rslt.dwProductVersionMS mod 65536,
    Rslt.dwProductVersionLS div 65536,
    Rslt.dwProductVersionLS mod 65536]);
  finally
    FreeMem(VersionBlock);
  end;
end;


Lord Delfos 22-12-2009 20:58:20

Gracias a todos muchach@s. Pero el problema sigue siendo el mismo. Cualquier fecha que tenga el archivo .exe, sea de creación, acceso o modificación, depende exclusivamente del sistema operativo. Hay ocasiones en las que estas fechas se cambian al pasar de un medio a otro (copia en CD, FTP, etc.) y entonces se me jode todo el sistema...

Teóricamente los ejecutables tienen un campo fecha (que se obtiene con la API GetFileVersionInfo) pero Delphi no lo setea...

Habrá que seguir pensando, parece...

Casimiro Notevi 22-12-2009 21:19:03

Cita:

Empezado por Lord Delfos (Mensaje 349367)
Gracias a todos muchach@s. Pero el problema sigue siendo el mismo. Cualquier fecha que tenga el archivo .exe, sea de creación, acceso o modificación, depende exclusivamente del sistema operativo. Hay ocasiones en las que estas fechas se cambian al pasar de un medio a otro (copia en CD, FTP, etc.) y entonces se me jode todo el sistema...
Teóricamente los ejecutables tienen un campo fecha (que se obtiene con la API GetFileVersionInfo) pero Delphi no lo setea...
Habrá que seguir pensando, parece...

Creo que no has probado bien, la opción que he puesto, que yo sepa, mantiene la fecha del ejecutable.
Aunque puede ser que no lo haga y no me haya fijado.

Lord Delfos 23-12-2009 21:27:40

Gracias Casimiro, pero sí, la fecha puede modificarse sin querer y FileAge depende de la fecha de creación, así que cualquier modificación a eso... pues fuiste, se te jode el programa.

Casimiro Notevi 23-12-2009 21:43:34

No entiendo entonces, ¿qué quiéres decir?, que si tengo mi ejecutable y lo copio a otro ordenador, por ejemplo, ya cambia la fecha?

Lord Delfos 24-12-2009 00:00:37

Cita:

Empezado por Casimiro Notevi (Mensaje 349440)
No entiendo entonces, ¿qué quiéres decir?, que si tengo mi ejecutable y lo copio a otro ordenador, por ejemplo, ya cambia la fecha?

A ver, a ver. La fecha de creación/modificación/último acceso está almacenada en el sistema de archivos, sea NTFS, FAT32 o lo que sea, NO en el ejecutable.

Así que, potencialmente hablando, cualquier proceso que "cree" el archivo en un dispositivo de almacenamiento cualquiera, puede modificar la fecha de creación. Es decir, si vos recibís el archivo por FTP, Windows va a crear una nueva entrada de archivo y después copiar el contenido de lo que está recibiendo. Generalmente los datos de fechas son copiados junto con el archivo porque el SO es lo suficientemente inteligente, pero otras veces (y esto está librado a la suerte) no copia nada.

De ahí el problema de la fecha.

Casimiro Notevi 24-12-2009 00:13:40

No sé en qué estaba pensando.
¿Y no te vale el "build" para tu propósito?, v1.3.115, p.e.?

Lord Delfos 24-12-2009 19:52:52

Sí, el build me viaja. Lo que pasa es que yo quiero mostrar todos los números de versión, junto con la fecha en la que se compiló. Algo así como

"Versión 1.3.4.87. Compilada 12/12/2009 a las 17:34."

Digamos que me gustaría que fuera automático el asunto, así no tengo que andar modificando el texto cada vez que compilo la versión "final". Hata ahora solamente puedo hacerlo con los número de versión, pero de la fecha... pues nada.

Casimiro Notevi 24-12-2009 22:15:18

Cita:

Empezado por Lord Delfos (Mensaje 349513)
Sí, el build me viaja. Lo que pasa es que yo quiero mostrar todos los números de versión, junto con la fecha en la que se compiló. Algo así como

"Versión 1.3.4.87. Compilada 12/12/2009 a las 17:34."

Digamos que me gustaría que fuera automático el asunto, así no tengo que andar modificando el texto cada vez que compilo la versión "final". Hata ahora solamente puedo hacerlo con los número de versión, pero de la fecha... pues nada.


Exactamente eso es lo que yo quería, pero no me había fijado en lo de la fecha, estaba tan tranquilo que se guardaba :s

Lord Delfos 28-12-2009 21:47:34

¡Sí! ¡Al fin puede hacerlo! Qué hijo de ·$·%$!@. Se me complicó el asunto.

Al final todo fue obra del querido CnWizards, que permite ejecutar un script antes de compilar un proyecto cualquiera. Asi que me hice un script que crea un archivo con las lineas

Código Delphi [-]
const FechaCompilacion = '28/12/2009 a las 12:14';

... usando la función Now, lógicamente, así uno tiene la fecha y hora actual en la que se está corriendo el script.

Después agrego un $INCLUDE en mi código para que importe ese archivo y listo. Ahora tengo una constante que tiene la fecha de compilación.

Qué bueno, con qué poco uno se pone contento en estos días...

Saludos y gracias a todos por los aportes.

Casimiro Notevi 28-12-2009 22:28:20

Bueno, bueno... amigo :D explica cómo se hace el script ese del cnwizard, porfa :)

Lord Delfos 28-12-2009 22:54:20

Hmmmm... Parece ser un buen secreto, no sé si darlo gratis...:cool:

En fin, la cosa es así:

[1] Tener instalado el CnWizards, claro.
[2] Vas "Script Wizard\Script Window".
[3] Aparece una ventanita. Se hace click en "new". Esto abre una ventana en el IDE de Delphi.
[4] Uno escribe el código correspondiente.

Código Delphi [-]
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

var Lineas: TStringList;

begin
  Lineas:= TStringList.Create;
  try
    Lineas.Add('const FechaCompilacion = ''' + FormatDatetime('dd/mm/yyyy', Now) + ''';');
    Lineas.Add('const HoraCompilacion = ''' + FormatDatetime('hh:nn', Now) + ''';');
    Lineas.SaveToFile('C:\Delphi\Utils\FechaCompilacion.inc');
  finally
    Lineas.Free;
  end;

y lo guardás en cualquier lado.

[5] Vas a "Script Wizard\Script Library". La ventana que aparece te muestra todos los scripts que tengas declarados a la izquierda (probablemente no tengas ninguno).

[6] Hacés click en "Add", le ponés algún nombre. Elegís el archivo que acabás de guardar en la TextBox "Filename".

[7] Ahora seleccionás fmBeforeCompile en el Treeview de la derecha. Para que el script se corra antes de compilar.

[8] Finalmente agregás un $I en tu código para importar el archivo que tiene las constantes:

Código Delphi [-]
unit Unit1;

type TForm1 = class(TForm)

[...]

end

implementation

{$R *.res}

{$I 'C:\Delphi\Utils\FechaCompilacion.inc'}


procedure TForm1.OnCreate(Sender: TObject);
begin
  ShowMessage('Compilado el ' + FechaCompilacion + ' a las ' + HoraCompilacion);
end;

Lógicamente, dado que el $I importa el código directamente donde se declara, hay que ponerlo en un lugar donde se permita declarar constantes.

Y listo. Por supuesto que el script se ejecuta cada vez que se compila cualquier proyecto, así que con cualquier cosa uno sobreescribe el archivo con las constantes. Afortunadamente resulta irrelevante ya que se usa únicamente para "leer" la hora y la fecha.

¿Sé entiende todo esto? El que no entiende, pues pregunte.

Neftali [Germán.Estévez] 29-12-2009 11:29:58

Gracias por la explicación; Muy interesante...

Casimiro Notevi 29-12-2009 11:40:05

Ya lo he "pirateado" ¿o tiene licencia libre? :D

Lepe 29-12-2009 14:45:22

Pues yo he tenido un deja vú :o

El año pasado hice varios de ese estilo, pero vamos, que no es necesario escribir en un fichero externo, cnWizard permite modificar cualquier archivo del proyecto delphi que tengas, de forma que esa constante se podría incluir en una unidad tuya, o incluso que cree un nuevo .pas con la constante y agregue esa unidad al proyecto automáticamente.

Si eso... mira este mensaje

Casimiro Notevi 29-12-2009 20:02:51

Entonces, cómo sería, ¿escribiendo en la ventanita que sale al dar a "nuevo script"?

Lord Delfos 29-12-2009 21:26:16

Cita:

Empezado por Lepe (Mensaje 349691)
... cnWizard permite modificar cualquier archivo del proyecto delphi que tengas, de forma que esa constante se podría incluir en una unidad tuya, o incluso que cree un nuevo .pas con la constante y agregue esa unidad al proyecto automáticamente.

Es muy interesante tu idea, pero tengo una duda.

¿Hay alguna manera de saber, desde un script, cómo se llama el proyecto o su ruta? Es decir, yo puedo agregar lineas de código al archivo que tengo editando, pero ¿qué pasa si quiero que escriba en otro archivo del proyecto? Tendría que hacer un script por cada proyecto, para poder cambiarle el archivo en el que tiene que escribir...

Es decir, sería muy bueno poder saber el nombre del proyecto (y/o su ruta) así uno podría crear una unidad en la misma ruta del proyecto y agregarla a la uses... ¿Se entiende lo que digo?

Lepe 29-12-2009 23:34:51

Casimiro, los scripts los escribes si quieres en el mismo delphi (como si fuera un .pas independiente con el siguiente esquema y uses. Verás que los uses no son los standard de delphi, sino aquellos .pas situados en la carpeta de CnWizards:
- PSDecl: clases y rutinas que se pueden usar en los scripts
- PSDeclEx: rutinas que interactuan con el IDE. Todo lo que puedes hacer con el ratón en el IDE, puede hacerse con cnScripts.
(Pascal Script Declaration)

Lord Delfos: Por supuesto.
Código Delphi [-]
program Uno;
uses cnWizUtils, // para averigual el projecto
       ToolsApi,  // unidad con los tipos de datos


var Project: IOTAProject; // mira en cnWizards\PSDecl\ToolsApi.pas este tipo de datos,métodos, etc.

i:integer;

begin

writeln('Nombre del proyecto ' + CnOtaGetCurrentProjectName);
writeln('Fichero de proyecto ' + CnOtaGetCurrentProjectFileName);
writeln('Archivos en el proyecto:');
Project := CnOtaGetCurrentProject;
  for i := 0 to Project.GetModuleCount - 1 do
    writeln('  ' + Project.GetModule(i).GetFileName );
end;

end.

Os sugiero mirar la carpeta de cnWidzards\PSdemos (Pascal Script Demos) ;)

Un pequeño manual y mis propios scripts aqui: http://www.terawiki.clubdelphi.com/a...20tutorial.zip

Edito: Se me olvidaba, todo el contenido del zip descomprimirlo en la carpeta c:\archivos de programa\cnwizards\User\Scripts (scripts la teneis que crear vosotros).

Edit2: Para importar los cnscripts, abres el Script Library, y usas el cuarto botón por la izquierda (Import) eligiendo el archivo .xml de la carpeta User\Scripts, Importará sólo algunos scripts, el resto los tendréis que añadir a mano (lo siento, ayer era tarde y estaba algo cansado).

Como ya dije en el manual, todos los errores de compilación de los cnScripts y writeln que hagamos en ellos saldrán en el Script Window. Yo hago los scripts con Notepad++ ya que el IDE de delphi se quedará trabado en los uses y no puede compilar (se puede configurar el IDE para que busque en $(cnwizards)\PSDecl aunque yo no lo tengo configurado)

Saludos

Lord Delfos 31-12-2009 20:27:14

¡Ajá!

¡Lepe, son como el Papa Noel de CnWizards! ¿Para reyes, no me traes una bicicleta, viejo?:p

Mil gracias.

Casimiro Notevi 01-01-2010 00:53:51

Lepe, al ver tu tutorial he recordado que eso "ya lo había visto antes" y efectivamente, buscando, buscando... lo encontré en mi directorio "ParaEstudiarlo" :s

santiago14 27-12-2014 15:32:04

Buenas, buscando y buscando me topé con este post. Resulta que para mi trabajo necesito saber la fecha de compilación del ejecutable. Build que le dicen.
Aquí ví una variada gama de cosas así que me puse a probar, indagué un poco mas y me encontré con esto.

La fecha/hora de compilación está en el espacio de memoria "LastCompiledTime", que no aparece en el ejemplo, así que yo lo agregué en mi código...
Código Delphi [-]
procedure TfrmGetDateVersion.btnDetailsFileClick(Sender: TObject);
type
  TEXEVersionData = record
    CompanyName,
    FileDescription,
    FileVersion,
    InternalName,
    LegalCopyright,
    LegalTrademarks,
    OriginalFileName,
    ProductName,
    ProductVersion,
    Comments,
    PrivateBuild,
    SpecialBuild,
    LastCompiledTime:string;
  end;

var
  vData:TEXEVersionData;

  function GetEXEVersionData(const FileName: string): TEXEVersionData;
  type
    PLandCodepage = ^TLandCodepage;
    TLandCodepage = record
      wLanguage,
      wCodePage: word;
    end;
  var
    dummy,
    len: cardinal;
    buf, pntr: pointer;
    lang: string;
  begin
    len := GetFileVersionInfoSize(PChar(FileName), dummy);
    if len = 0 then
      RaiseLastOSError;
    GetMem(buf, len);
    try
      if not GetFileVersionInfo(PChar(FileName), 0, len, buf) then
        RaiseLastOSError;

      if not VerQueryValue(buf, '\VarFileInfo\Translation\', pntr, len) then
        RaiseLastOSError;

      lang := Format('%.4x%.4x', [PLandCodepage(pntr)^.wLanguage, PLandCodepage(pntr)^.wCodePage]);

      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\CompanyName'), pntr, len){ and (@len <> nil)} then
        result.CompanyName := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\FileDescription'), pntr, len){ and (@len <> nil)} then
        result.FileDescription := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\FileVersion'), pntr, len){ and (@len <> nil)} then
        result.FileVersion := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\InternalName'), pntr, len){ and (@len <> nil)} then
        result.InternalName := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LegalCopyright'), pntr, len){ and (@len <> nil)} then
        result.LegalCopyright := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LegalTrademarks'), pntr, len){ and (@len <> nil)} then
        result.LegalTrademarks := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\OriginalFileName'), pntr, len){ and (@len <> nil)} then
        result.OriginalFileName := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\ProductName'), pntr, len){ and (@len <> nil)} then
        result.ProductName := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\ProductVersion'), pntr, len){ and (@len <> nil)} then
        result.ProductVersion := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\Comments'), pntr, len){ and (@len <> nil)} then
        result.Comments := PChar(pntr);
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\PrivateBuild'), pntr, len){ and (@len <> nil)} then
        result.PrivateBuild := PChar(pntr);
//Esto lo agregué yo
      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LastCompiledTime'), pntr, len){ and (@len <> nil)} then
        result.LastCompiledTime := PChar(pntr);

      if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\SpecialBuild'), pntr, len){ and (@len <> nil)} then
        result.SpecialBuild := PChar(pntr);

    finally
      FreeMem(buf);
    end;
  end;
begin
  if dlg1.Execute() then
  begin
    vData:=GetEXEVersionData(dlg1.FileName);
    mmo2.Lines.Text:='1';
  end ;
end;

Con esto podemos saber la fecha de última compilación. Sigo haciendo pruebas pero me parece que es el camino.

La cosa me devuelve un string con un campo que tiene la fecha y la hora, queda pasar eso a TimeStamp para completar la secuencia.

Espero haber ayudado.

Santiago.

santiago14 27-12-2014 15:53:52

Me parece que "LastCompiledTime" está disponible desde Delphi 7 en adelante. Probé con un compilado con mi viejo D6 y ese campo aparece vacío.

Hay que tener cuidado, en este caso, al transformar la fecha/hora.


La franja horaria es GMT +2. Ahora son las 08:11:27.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi