Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Cambiar Versión Ejecutable (https://www.clubdelphi.com/foros/showthread.php?t=96459)

javier14 26-10-2023 09:08:48

Cambiar Versión Ejecutable
 
Necesito un procedimiento que pasado un archivo ejecutable por parámetro le cambie el FILE VERSION. (No es cambiar la versión en el programa que estoy, sino en otro ejecutable)

Neftali [Germán.Estévez] 26-10-2023 10:36:45

Para obtener la información del ejecutable puedes empezar por las APIs: GetFileVersionInfoand VerQueryValue (esta información puedes obtenerla de la wiki de embarcadero https://docwiki.embarcadero.com/RADS...n/Version_Info).

Para actualizarlo con el nuevo valor, revisa las APIs, BeginUpdateResource, UpdateResource y EndUpdateResource.

javier14 26-10-2023 11:04:54

Código Delphi [-]
function FileVersionToInteger(const version: string): Integer;
var
  parts: TArray<string>;
  i, factor: Integer;
begin
  parts := version.Split(['.']);
  Result := 0;
  factor := 1;
  for i := High(parts) downto Low(parts) do
  begin
    Result := Result + StrToInt(parts[i]) * factor;
    factor := factor * 1000;
  end;
end;

procedure TForm1.CambiarVersionArchivo(const nombreArchivo: string;
  nuevaVersion: string);
var
  info: VS_FIXEDFILEINFO;
  handle, len: DWORD;
  datos, ptr: PChar;
  errorCode : DWORD;
begin
  nuevaVersion := nuevaVersion.Replace('.', '');
  nuevaVersion := nuevaVersion.PadRight(4, '0');
  nuevaVersion := nuevaVersion.PadLeft(8, '0');
  var nuevaVersionInt := FileVersionToInteger(nuevaVersion);

  handle := BeginUpdateResource(PChar(nombreArchivo), False);
  if handle = 0 then
    RaiseLastOSError;

  len := GetFileVersionInfoSize(PChar(nombreArchivo), handle);
  if len = 0 then
  begin
    EndUpdateResource(handle, False);
    RaiseLastOSError;
  end;

  datos := AllocMem(len);
  try
    if not GetFileVersionInfo(PChar(nombreArchivo), handle, len, datos) then
    begin
      EndUpdateResource(handle, False);
      RaiseLastOSError;
    end;

    if VerQueryValue(datos, '\', Pointer(ptr), len) then
    begin
      Move(ptr^, info, sizeof(info));

      info.dwFileVersionMS := nuevaVersionInt;
      info.dwFileVersionLS := nuevaVersionInt;

      Move(info, ptr^, sizeof(info));
    end
    else
    begin
      errorCode := GetLastError;
      ShowMessage('VerQueryValue Error: ' + IntToStr(errorCode));
      EndUpdateResource(handle, False);
      RaiseLastOSError;
    end;

    if not EndUpdateResource(handle, False) then
    begin
      errorCode := GetLastError;
      ShowMessage('EndUpdateResource Error: ' + IntToStr(errorCode));
      RaiseLastOSError;
    end;
  finally
    FreeMem(datos);
  end;
end;

Lo llamo en el OnClick del botón:
CambiarVersionArchivo('C:\Users\javier\myfile.exe', '6.7.8.9');

Pero me salen los errores:

Primero:

Cita:

· ShowMessage: EndUpdateResource Error: 87
Segundo:

Cita:

· Excepción: A call to an OS function failed
¿ Qué puede pasar ?

Neftali [Germán.Estévez] 26-10-2023 13:09:19

Veo los BeginUpdate... y los EndUpdate..., pero no veo por ningún sitio la llamada a UpdateResource.

javier14 26-10-2023 15:22:09

procedure TForm1.CambiarVersionArchivo(const nombreArchivo: string;
nuevaVersion: string);
var
info: VS_FIXEDFILEINFO;
handle, len: DWORD;
datos, ptr: PChar;
errorCode: DWORD;
nuevaVersionInt: Integer;
begin
nuevaVersion := nuevaVersion.Replace('.', '');
nuevaVersion := nuevaVersion.PadRight(4, '0');
nuevaVersion := nuevaVersion.PadLeft(8, '0');
nuevaVersionInt := FileVersionToInteger(nuevaVersion);

handle := BeginUpdateResource(PChar(nombreArchivo), False);
if handle = 0 then
RaiseLastOSError;

len := GetFileVersionInfoSize(PChar(nombreArchivo), handle);
if len = 0 then
begin
EndUpdateResource(handle, False);
RaiseLastOSError;
end;

datos := AllocMem(len);
try
if not GetFileVersionInfo(PChar(nombreArchivo), handle, len, datos) then
begin
EndUpdateResource(handle, False);
RaiseLastOSError;
end;

if VerQueryValue(datos, '\', Pointer(ptr), len) then
begin
Move(ptr^, info, SizeOf(info));

info.dwFileVersionMS := nuevaVersionInt;
info.dwFileVersionLS := nuevaVersionInt;

if not UpdateResource(handle, RT_VERSION, PChar(1), 0, datos, len) then
begin
errorCode := GetLastError;
ShowMessage('UpdateResource Error: ' + IntToStr(errorCode));
EndUpdateResource(handle, False);
RaiseLastOSError;
end;
end
else
begin
errorCode := GetLastError;
ShowMessage('VerQueryValue Error: ' + IntToStr(errorCode));
EndUpdateResource(handle, False);
RaiseLastOSError;
end;

if not EndUpdateResource(handle, False) then
begin
errorCode := GetLastError;
ShowMessage('EndUpdateResource Error: ' + IntToStr(errorCode));
RaiseLastOSError;
end;
finally
FreeMem(datos);
end;
end;

Algo asi? No termina de funcionar pero debe ser algo por el estilo

Casimiro Notevi 26-10-2023 19:59:27

Por favor, no olvides usar las etiquetas para código:

javier14 30-10-2023 14:44:01

Cambio FileVersion Ejecutable
 
Sabéis porque no cambia el FileVersion? Es lo único que no se modifica...

Código Delphi [-]
function UpdateExeInfo(const ExePath, CompanyName, FileDescription,
     FileVersion, InternalName, LegalCopyright, LegalTrademarks, OriginalFileName,
      ProgramID, ProductName, ProductVersion, Comments: string): Boolean;
type
  PLangAndCodePage = ^TLangAndCodePage;
  TLangAndCodePage = packed record
    wLanguage: Word;
    wCodePage: Word;
  end;
var
  Size, Unused: DWORD;
  VerData: PByte;
  Value: Pointer;
  Len, VerLen, I: UINT;
  Translate: PLangAndCodePage;
  KeyName: WideString;
  AFileVersion: LPWSTR;
  hUpdate: THandle;
  Updated: BOOL;
begin
  Result := False;
  if not FileExists(ExePath) then
    Exit;

  Size := GetFileVersionInfoSize(PChar(ExePath), Unused);
  if Size <> 0 then
  begin
    GetMem(VerData, Size);
    try
      if GetFileVersionInfo(PChar(ExePath), 0, Size, VerData) then
      begin
        Value := nil;
        Len := 0;
        VerQueryValue(VerData, '\', Value, Len);

        Value := nil;
        Len := 0;
        VerQueryValue(VerData, '\VarFileInfo\Translation', Value, Len);

        Translate := PLangAndCodePage(Value);
        for I := 0 to (Len div SizeOf(TLangAndCodePage)) - 1 do
        begin

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'CompanyName';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(CompanyName));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'FileDescription';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(FileDescription));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'FileVersion';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(FileVersion));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'InternalName';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(InternalName));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'LegalCopyright';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(LegalCopyright));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'LegalTrademarks';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(LegalTrademarks));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'OriginalFileName';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(OriginalFileName));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'ProgramID';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(ProgramID));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'ProductName';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(ProductName));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'ProductVersion';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(ProductVersion));
          end;

          KeyName := '\StringFileInfo\' + IntToHex(Translate^.wLanguage, 4) +
            IntToHex(Translate^.wCodePage, 4) + '\' + 'Comments';
          Value := nil;
          VerLen := 0;
          if VerQueryValueW(VerData, PWideChar(KeyName), Value, VerLen) then
          begin
            AFileVersion := PWideChar(Value);
            ZeroMemory(AFileVersion, VerLen * SizeOf(WideChar));
            wsprintfW(AFileVersion, PWideChar(Comments));
          end;

          Inc(Translate);
        end;

        hUpdate := BeginUpdateResource(PChar(ExePath), False);
        if hUpdate <> 0 then
        begin
          Updated := UpdateResource(hUpdate, RT_VERSION,
            MAKEINTRESOURCE(VS_VERSION_INFO), MAKELANGID(LANG_NEUTRAL,
            SUBLANG_NEUTRAL), VerData, Size);
          EndUpdateResource(hUpdate, not Updated);
        end;
      end;
    finally
      FreeMem(VerData);
    end;
  end;
end;


La franja horaria es GMT +2. Ahora son las 17:06:53.

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