¿Cómo modificar / instalar una ruta de biblioteca de componentes en Delphi IDE sin hacerlo manualmente?

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

Pregunta

Estoy preparando un instalador (Configuración de Inno) para instalar mi paquete de componentes en Delphi Xe sin tener que jugar manualmente en el IDE.

Necesito modificar la ruta de la biblioteca de Delphi, por ejemplo, para eliminar parte de ella (por ejemplo, xxx;MyOldPath;yyy) e inserte una nueva ruta, xxxx;MyNewPath;yyyy. ¿Existe una forma preferida de hacer esto o tendré que escribir una utilidad para hacerlo?

Gracias

¿Fue útil?

Solución

La modificación de la ruta es la manipulación básica de la cadena: lees la ruta actual del registro, la manipula para satisfacer sus necesidades, escríbala.

Probablemente pueda escribir una función de script de configuración inno para que no tenga dependencias externas. O escriba una DLL DLPHI que se usa en el guión de Inno Setup para que sea más fácil depurar.


Editar

Aquí hay una versión modificada de una rutina que estoy usando en producción. Leerá toda la lista de rutas de los Search Path valor de registro o el Browsing Path (Cualquier otra ruta), potencialmente elimine algunas rutas y agregue algunas rutas si aún no existen.

procedure UpdateDelphiPaths(const RegistryKey, RegistryValue: string; PathsToRemove, PathsToAdd: TStrings);
var R:TRegistry;
      SKeys:TStringList;
      Found:Boolean;
      Updated:Boolean;
      i,j:Integer;
      s:string;
      R_Globals:TRegistry;

  // This function normalises paths in comparasions
  function PrepPathForComparasion(const Path:string):string;
  begin
    if Path = '' then Result := '\'
    else
      if Path[Length(Path)] = '\' then
        Result := LowerCase(Path)
      else
        Result := LowerCase(Path) + '\';
  end;

  function PathMatchesRemoveCriteria(const Path:string): Boolean;
  var i:Integer;
  begin
    // This needs to be addapted to match your criteria!
    for i:=0 to PathsToRemove.Count-1 do
      if AnsiPos(PathsToRemove[i], Path) <> 0 then
        Exit(True);
    Result := False;
  end;

begin
  R := TRegistry.Create;
  try
    R.RootKey := HKEY_CURRENT_USER;
    if R.OpenKey(RegistryKey + '\Library', False) then
      if R.ValueExists(RegistryValue) then
      begin
        SKeys := TStringList.Create;
        try
          SKeys.Delimiter := ';';
          SKeys.StrictDelimiter := True;
          SKeys.DelimitedText := R.ReadString(RegistryValue);

          Updated := False;

          // Look at all the paths in the PathsToAdd list, if any one's missing add it to the list and mark
          // "Updated".
          for i:=0 to PathsToAdd.Count-1 do
          begin
            Found := False;
            for j:=0 to SKeys.Count-1 do
              if LowerCase(Trim(SKeys[j])) = LowerCase(Trim(PathsToAdd[i])) then
                Found := True;
            if not Found then
            begin
              SKeys.Add(PathsToAdd[i]);
              Updated := True;
            end;
          end;

          // Look at every single path in the current list, if it's not in the "PathsToAdd" and it matches
          // a name in "PathsToRemove", drop it and mark "Updated"
          i := 0;
          while i < SKeys.Count do
          begin
            if PathMatchesRemoveCriteria(SKeys[i]) then
              begin
                // Path matches remove criteria! It only gets removed if it's not actually present in
                // PathsToAdd
                Found := False;
                for j:=0 to PathsToAdd.Count-1 do
                begin
                  if PrepPathForComparasion(SKeys[i]) = PrepPathForComparasion(PathsToAdd[j]) then
                    Found := True;
                end;
                if not Found then
                  begin
                    SKeys.Delete(i);
                    Updated := True;
                  end
                else
                  Inc(i);
              end
            else
              Inc(i);
          end;

          // If I've updated the SKeys in any way, push changes back to registry and force updates
          if Updated then
          begin
            s := SKeys[0];
            for i:=1 to SKeys.Count-1 do
              if SKeys[i] <> '' then
              begin
                s := s + ';' + SKeys[i];
              end;
            R.WriteString(RegistryValue, s);

            // Force delphi to re-load it's paths.
            R_Globals := TRegistry.Create;
            try
              R_Globals.OpenKey(RegistryKey + '\Globals', True);
              R_Globals.WriteString('ForceEnvOptionsUpdate', '1');
            finally R_Globals.Free;
            end;

          end;

        finally SKeys.Free;
        end;
      end;
  finally R.Free;
  end;
end;

Desde el código Delphi puedo llamar a la rutina así, para asegurarme de que esté instalada la última ruta de búsqueda a una biblioteca determinada:

var ToRemove, ToAdd: TStringList;
begin
  ToRemove := TStringList.Create;
  try
    ToAdd := TStringList.Create;
    try
      ToRemove.Add('LibraryName\Source');
      ToAdd.Add('C:\LibraryName\Source');
      UpdateDelphiPaths('Software\CodeGear\BDS\7.0', 'Test Path', ToRemove, ToAdd);
    finally ToAdd.Free;
    end;
  finally ToRemove.Free;
  end;
end;

Observe ambos ToRemove y ToAdd. Puedo especificar de forma segura una ruta de búsqueda en las listas de eliminar y agregar: las rutas solo se eliminan si coinciden con los criterios "eliminados" pero también no están en la lista "Toadd". También tenga en cuenta el PathMatchesRemoveCriteria función.

Probablemente pueda modificar el código para que funcione directamente desde el propio InnoScript, o puede colocar el código en una DLL y usar la DLL desde el instalador. La variante DLL tiene el mérito de ser fácilmente depurada en Delphi y muy fácil con Inno mismo; La variante Inno tiene el mérito de no tener dependencias externas, pero el código necesitaría ser adaptado y depurado.

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