PDA

Ver la Versión Completa : Cambiar Versión Ejecutable


javier14
26-10-2023, 09:08:48
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: GetFileVersionInfo (https://www.clubdelphi.com/foros/GetFileVersionInfo and VerQueryValue)and VerQueryValue (https://www.clubdelphi.com/foros/GetFileVersionInfo and VerQueryValue) (esta información puedes obtenerla de la wiki de embarcadero https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Version_Info).

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

javier14
26-10-2023, 11:04:54
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:


· ShowMessage: EndUpdateResource Error: 87


Segundo:


· 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:
https://www.clubdelphi.com/images/UtilizarTAGs.png

javier14
30-10-2023, 14:44:01
Sabéis porque no cambia el FileVersion? Es lo único que no se modifica...

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;