Cómo convertir un valor de versión de cadena a un valor numérico en los scripts de Inno Setup?

StackOverflow https://stackoverflow.com/questions/1097462

Pregunta

Quiero desarrollar un paquete de instalación para actualizar un paquete existente de forma condicional. Quiero comprobar la versión del software existente en contra de la versión a-ser-instalado. Con el fin de hacer eso, tengo que comparar las cadenas de versión.

¿Cómo puedo convertir el valor de cadena a un valor numérico en un script de configuración Inno?

RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Blah blah', 'Version', version)
version = 'V1.R2.12';
numVersion := ??string_to_numerical_value??(version);
¿Fue útil?

Solución

Esto es un poco más complicado, ya que se quiere manejar versiones como 'V1.R2.12' y 'V0.R15.42' correctamente - con la simple conversión en la otra respuesta que se obtendría 1212 y 1542, que no sería comparar la manera en que se puede esperar.

Es necesario decidir qué tan grande puede ser cada parte del número de versión, y multiplicar las partes por ese valor para obtener un número final correcta. Algo como esto:

[Code]
function string_to_numerical_value(AString: string; AMaxVersion: LongWord): LongWord;
var
  InsidePart: boolean;
  NewPart: LongWord;
  CharIndex: integer;
  c: char;
begin
  Result := 0;
  InsidePart := FALSE;
  // this assumes decimal version numbers !!!
  for CharIndex := 1 to Length(AString) do begin
    c := AString[CharIndex];
    if (c >= '0') and (c <= '9') then begin
      // new digit found
      if not InsidePart then begin
        Result := Result * AMaxVersion + NewPart;
        NewPart := 0;
        InsidePart := TRUE;
      end;
      NewPart := NewPart * 10 + Ord(c) - Ord('0');
    end else
      InsidePart := FALSE;
  end;
  // if last char was a digit the last part hasn't been added yet
  if InsidePart then
    Result := Result * AMaxVersion + NewPart;
end;

Puede probar esto con el siguiente código:

function InitializeSetup(): Boolean;
begin
  if string_to_numerical_value('V1.R2.12', 1) < string_to_numerical_value('V0.R15.42', 1) then
    MsgBox('Version ''V1.R2.12'' is not as recent as version ''V0.R15.42'' (false)', mbConfirmation, MB_OK);
  if string_to_numerical_value('V1.R2.12', 100) > string_to_numerical_value('V0.R15.42', 100) then
    MsgBox('Version ''V1.R2.12'' is more recent than version ''V0.R15.42'' (true)', mbConfirmation, MB_OK);
  Result := FALSE;
end;

Si se pasa de 10, 100 o 1000 para AMaxVersion depende del número y la variedad de su Versión partes numéricas. Tenga en cuenta que no debe desbordar la variable de resultado LongWord, que tiene un valor máximo de 2 ^ 32 -. 1

Otros consejos

No he probado que (y mis conocimientos Pascal es un poco oxidado), pero algo como lo siguiente debería funcionar:

function NumericVersion(s: String): Integer;
var
  i: Integer;
  s1: String;
begin
  s1 := '';
  for i := 0 to Length(s)-1 do
    if (s[i] >= '0') and (s[i] <= '9') then
      s1 := s1 + s[i];

  Result := StrToIntDef(s1, 0);
end;

Por favor, no que tendrá que jugar con el valor de inicio y finalización de i ya que no estoy seguro de si está basado en cero o no (s[0] puede contener la longitud de la cadena si se trata de una "cadena Pascal ").

Yo he implementado dos cadenas de versión (en realidad una cadena y un valor DWORD) en el Registro para superar la complejidad.

displayversion="v1.r1.0"
version="10100"   (=1*10^4 + 1*10^2 + 0*10^0)

Eso es simple. Aunque no es una respuesta a esta pregunta, sin embargo, se podría pensar al revés cuando se enfrentan a la complejidad, que podría evitarse de manera más sencilla.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top