Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Ayuda con edicion de archivo inno setup (https://www.clubdelphi.com/foros/showthread.php?t=88943)

walterk. 30-08-2015 16:23:54

Ayuda con edicion de archivo inno setup
 
Hola comunidad..
Necesito si me pueden dar una mano con la lectura y escritura en un archivo tipo txt. El archivo esta compuesto de la siguiente manera:

Cita:

[Area.133] -------------------------ESTE ES EL ULTIMO ITEM QUE APARECE EN EL ARCHIVO
Title=SA98
Local=SA98\SA98 SL
Layer=133 --------------------------AQUI REPITE EL MISMO NUMERO DE AREA
Active=TRUE
Required=FALSE

-------------------------------------------------------------------------------------------------------------------------------------------------------------

[Area.134] --------------------------ESTE SERIA EL QUE TENGO QUE AGREGAR SUIGUIENDO EL ORDEN DE NUMEROS
Title=SOb
Local=AS\SOL
Layer=134 --------------------------Y LO MISMO EN ESTE CASO QUE REPITE EL MISMO NUMERO DE AREA
Active=TRUE
Required=FALSE

El mismo necesito modificarlo cuando hago la instalacion de las areas(esa parte la tengo lista y funcionando), pero aqui no se como resolverlo.
Agradezco cualquier mano que me puedan brindar.

AgustinOrtu 30-08-2015 19:31:14

Cita:

pero aqui no se como resolverlo.
Pero, que es lo que necesitas hacer?

walterk. 30-08-2015 21:12:47

Hola Agustin, gracias por responderme, lo que necesito es que cada vez que instale un area nueva, incremente los numeros en los dos lugares marcados y escriba el texto del area, como puse en el ejemplo, no se si se entiende? el dato title, Local, Active y Required son fijos pero no se como hacer que abra el archivo lea cual e el ultimo y agregue el numero incrementado a Area.134 y lo copie a layer.

[Area.134] --------------------------ESTE SERIA EL QUE TENGO QUE AGREGAR SUIGUIENDO EL ORDEN DE NUMEROS
Title=SOb
Local=AS\SOL
Layer=134 --------------------------Y LO MISMO EN ESTE CASO QUE REPITE EL MISMO NUMERO DE AREA
Active=TRUE
Required=FALSE

Gracias nuevamente por tu tiempo.

Casimiro Noteví 30-08-2015 21:16:23

Bienvenido a clubdelphi, como siempre aconsejamos a los nuevos, no olvides leer nuestra guía de estilo, gracias por tu colaboración :)

ecfisa 31-08-2015 14:55:44

Hola walterk.

Si tenes la certeza de que las cadenas a buscar ('[Area.' y 'Layer=') siempre existirán en el archivo, podrías hacer:
Código Delphi [-]
uses StrUtils;

procedure ActualizarArea(const FileName, Area: string);
var
  Strings: TStrings;
  i, p1, p2: Integer;
  cad : string;
begin
  Strings := TStringList.Create;
  try
    Strings.LoadFromFile(FileName);

    // Area
    for i := 0 to Strings.Count-1 do
      if Pos('[Area.', Strings[i]) <> 0 then Break;
    cad  := Strings[i];
    p1 := Pos('[Area.', cad);
    p2 := PosEx(']', cad, p1);
    Delete(cad, p1 + 6, p2 - p1 - 6);
    Insert(Area, cad, p1 + 6);
    Strings[i] := cad;

    // Layer
    for i := 0 to Strings.Count-1 do
      if Pos('Layer=', Strings[i]) <> 0 then Break;
    cad := Strings[i] + '~'; // indicador de final
    p1  := Pos('Layer=', cad);
    p2  := PosEx('~', cad, p1);
    Delete(cad, p1 + 6, p2 - p1 - 6 + 1);
    Insert(Area, cad, p1 + 6);
    Strings[i] := cad;

    Strings.SaveToFile(FileName);
  finally
    Strings.Free;
  end;
end;
Ejemplo de uso:
Código Delphi [-]
const
  FNAME = 'area.txt';

procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Lines.LoadFromFile(FNAME);
end;

procedure TForm1.btNewVersionClick(Sender: TObject);
begin
  ActualizarArea(FNAME, '3141592654' ); // o también: ActualizarArea(FNAME, IntToStr(entero));
  Memo1.Lines.LoadFromFile('c:\tmp\area.txt');
end;


Saludos :)

Ñuño Martínez 01-09-2015 10:28:14

Yo creo que sería más adecuado usar un TINIFile. Su método ReadSections devuelve la lista de secciones, por lo que no tendrás que ir adivinándolas. Luego ya puedes usar el resto de métodos para obtener, modificar, crear y/o eliminar valores y secciones.

walterk. 02-09-2015 01:24:32

Hola gracias por tu respuesta y el trabajo que te has tomado en poner las imagenes, ahora te hago una consulta si es posible.
Tienes idea como incluir tu codigo en inno setup para que cumpla la funcion cuando instalo la zona deceada?.

Gracias nuevamente por tu tiempo.

olbeup 02-09-2015 09:08:37

Cita:

Empezado por Ñuño Martínez (Mensaje 496109)
Yo creo que sería más adecuado usar un TINIFile. Su método ReadSections devuelve la lista de secciones, por lo que no tendrás que ir adivinándolas. Luego ya puedes usar el resto de métodos para obtener, modificar, crear y/o eliminar valores y secciones.

Hola walterk.

Como dice Ñuño Martínez, seria mejor utilizar el TINIFile, pero también añadiria al princio del fichero para saber ciertas cosas de él, como saber el último registro que se ha añadido el último acceso y quién lo ha realizado, se puede poner más y más cosas, para saber más y mejor el contenido del fichero.

Cita:

[Area.Record]
LastRecord=133
LastAccess=02/09/2015
LastIDUser=26

[Area.133]
Title=SA98
Local=SA98\SA98 SL
Layer=133
Active=TRUE
Required=FALSE
La labor que ha hecho ecfisa esta muy bien y se lo ha currado, pero cuando hay muchos registros puede ser un poco pesado.

Un saludo.

ecfisa 02-09-2015 10:53:46

Hola olbeup.
Cita:

Empezado por olbeup (Mensaje 496138)
...
La labor que ha hecho ecfisa esta muy bien y se lo ha currado, pero cuando hay muchos registros puede ser un poco pesado.

La verdad, ahora no me parece una buena opción, creo que no capté correctamente la consigna de walterk:
Cita:

...no se como hacer que abra el archivo lea cual e el ultimo y agregue el numero incrementado a Area.134 y lo copie a layer...
Reviendo el texto, interpreto que se tiene que leer el último valor, incrementarlo en uno y reemplazar los valores anteriores. Y de ser así, el código del mensaje #5 no lo hace.

Saludos :)

Edito: Y si, definitivamente coincido con ustedes en la conveniencia de usar TIniFile en este caso. ;)

olbeup 02-09-2015 13:21:54

Un ejemplo con TIniFiles:

Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IniFiles, StdCtrls;

type
  TAreaHead = record
    LastArea: Integer;
    LastAccess: TDateTime;
    LastIDUser: Integer;
  end;

  TArea = record
    Area: Integer;
    Title: String;
    Local: String;
    Active: Boolean;
    Required: Boolean;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    AreaHead: TAreaHead;

    procedure LoadHeadArea;
    procedure InsertArea(objArea: TArea);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  LoadHeadArea;
end;

procedure TForm1.LoadHeadArea;
var
  IniAH: TIniFile;
begin
  IniAH := TIniFile.Create('C:\Areas\Area.txt');
    AreaHead.LastArea   := IniAH.ReadInteger('Area.Record', 'LastRecord', 0);
    AreaHead.LastAccess := IniAH.ReadDate('Area.Record', 'LastAccess', 0);
    AreaHead.LastIDUser := IniAH.ReadInteger('Area.Record', 'LastIDUser', 0);
  FreeAndNil(IniAH);
end;

procedure TForm1.InsertArea(objArea: TArea);
var
  IniA: TIniFile;
begin
  IniA := TIniFile.Create('C:\Areas\Area.txt');
    IniA.WriteString('Area.' + IntToStr(objArea.Area), 'Title', objArea.Title);
    IniA.WriteString('Area.' + IntToStr(objArea.Area), 'Local', objArea.Local);
    IniA.WriteInteger('Area.' + IntToStr(objArea.Area), 'Layer', objArea.Area);
    IniA.WriteBool('Area.' + IntToStr(objArea.Area), 'Active', objArea.Active);
    IniA.WriteBool('Area.' + IntToStr(objArea.Area), 'Required', objArea.Required);

    IniA.WriteInteger('Area.Record', 'LastRecord', ObjArea.Area);
    IniA.WriteDate('Area.Record', 'LastAccess', Now);
    IniA.WriteInteger('Area.Record', 'LastIDUser', 36);

  IniA.UpdateFile;
  FreeAndNil(IniA);

  LoadHeadArea;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  xArea: TArea;
begin
  // Pedir datos de los registros y después insertarlos en el Area.txt

  FillChar(xArea, SizeOf(xArea), #0);
  
  xArea.Area      := AreaHead.LastArea +1;
  xArea.Title     := 'SOb';
  xArea.Local     := 'AS\SOL';
  xArea.Active    := True;
  xArea.Required  := False;

  InsertArea(xArea);
end;

end.

Un saludo.

ecfisa 02-09-2015 15:45:43

Hola walterk.

olbeup te dió un muy buen ejemplo, pero ya escribí el código, así que te agrego otro :)

En este se seleccióna el mayor número del valor de la sección "Area" y se añade otra sección con el valor incrementado (sigo en dudas si deseas agregar una nueva o modificar el valor de la existente).
Código Delphi [-]
...

implementation

uses IniFiles;

const
  FNAME = 'c:\tmp\Areas.ini';

procedure AddNextSection(const FileName: TFileName);
var
  Sections  : TStringList;
  Values    : TStrings;
  IniFile   : TMemIniFile;
  NewArea,s : string;
  i, max    : Integer;
begin
  IniFile := TMemIniFile.Create(FNAME);
  try
    Sections := TStringList.Create;
    Values   := TStringList.Create;
    try
      IniFile.ReadSections(Sections);
      Sections.Sort;
      NewArea := Sections[Sections.Count-1];
      IniFile.ReadSectionValues(NewArea, Values);
      max := Pos('.', NewArea);
      max := StrToIntDef(Copy(NewArea, max+1, Length(NewArea)-max+1), 0);
      Inc(max);
      NewArea := Format('Area.%d', [max]);
      for i := 0 to Values.Count-1 do //(*)
      begin
        s := Values[i];
        if Pos('Layer=', s) <> 0 then s := Format('Layer=%d',[max]);
        IniFile.WriteString(NewArea, Copy(s, 1, Pos('=',s)-1),
          Copy(s, Pos('=',s)+1, MaxInt));
      end;
      IniFile.UpdateFile;
    finally
      Values.Free;
      Sections.Free;
    end;
  finally
    IniFile.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AddNextSection(FNAME);
end;
(*) Se podría simplificar con el método IndexOfName pero Delphi 7 carece de StrictDelimiter y toma el espacio como delimitador.

Saludos :)

AgustinOrtu 02-09-2015 18:39:39

Tambien se puede usar XML, ClientDataSet, Json

Si se usa ClientDataSet no tendrias problemas de eficiencia de busquedas y ademas ganarias todas las caracteristicas de un TDataSet. Filtrado, ordenado, cursores, controles Data-Aware

walterk. 02-09-2015 19:58:09

Cita:

Empezado por ecfisa (Mensaje 496152)
Hola walterk.
En este se seleccióna el mayor número del valor de la sección "Area" y se añade otra sección con el valor incrementado (sigo en dudas si deseas agregar una nueva o modificar el valor de la existente).

Hola Ecfisa, antes que nada quiero agradecer a todos por sus aportes y la muy buena predisposicion que tiene.Bueno ahora contesto tu pregunta y la explayo un poco.

La idea es agregar siempre un area nueva y que se haga de forma automatica sin la necesidad de la intervencion del usuario que lo instale.
Para que se entinda mejor, yo diseño el escenario en cuestion y con inno setup realizo la instalacion dentro del programa ubicando donde lo tienen instalado a traves del registro de windows(segun usuario, disco "C","D","E",etc).Los datos del escenario al crealo yo los tengo e iria ubicado en "Title=", pero lo que no se como hacer es que abra el archivo verifique cual es el ultimo area que existe en el archivo y agregue mi area incrementando el numero anterior +1 y tome de la variable desde inno setup si es posible para agregar la ubicacion de donde se intalo el escenario para poner ese dato en "Local=", los valores "Active=" y "Required=" van asi por default.

Espero haber aclarado un poco el tema y de ser necesario agrego el codigo que realice en inno setup para aclarar mas el panorama.

Saludos

ecfisa 02-09-2015 22:45:58

Hola walterk.
Cita:

Empezado por walterk. (Mensaje 496174)
La idea es agregar siempre un area nueva y que se haga de forma automatica sin la necesidad de la intervencion del usuario que lo instale.

Entonces creo que el código anterior te podría llegar a servir. Para ejemplificarlo, agregué un ListBox al formulario y este código:
Código Delphi [-]
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.LoadFromFile(FNAME);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AddNextSection(FNAME);
  ListBox1.Clear;
  ListBox1.Items.LoadFromFile(FNAME);
  ListBox1.TopIndex := ListBox1.Items.Count -1 ; 
end;

Resultado:


Saludos :)

walterk. 06-09-2015 08:46:39

Cita:

Empezado por ecfisa (Mensaje 496191)
Hola walterk.

Entonces creo que el código anterior te podría llegar a servir. Para ejemplificarlo, agregué un ListBox al formulario y este código:
Código Delphi [-]
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.LoadFromFile(FNAME);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AddNextSection(FNAME);
  ListBox1.Clear;
  ListBox1.Items.LoadFromFile(FNAME);
  ListBox1.TopIndex := ListBox1.Items.Count -1 ; 
end;

"Elimine la imagen porque no tengos permiso aun para poder mostrar imagenes."
Saludos :)

Muchisimas gracias por toda la ayuda, el ejemplo esta de lujo verdaderamente y es tal cual lo que necesito. Ahora una sola pregunta, tienen idea como pasar este codigo para que funcione en "inno setup", he porbado de varias maneras pero me tira errores. Desde ya muchisimas gracias.

Casimiro Noteví 06-09-2015 09:12:28

Cita:

Empezado por walterk. (Mensaje 496323)
he porbado de varias maneras pero me tira errores..

¿Qué maneras? ¿qué errores?

walterk. 06-09-2015 09:31:31

Cita:

Empezado por Casimiro Notevi (Mensaje 496324)
¿Qué maneras? ¿qué errores?

Por ejemplo copie el codigo tal cual y el error que me tira es: uses IniFiles (Unknown identifier)

Casimiro Noteví 06-09-2015 09:35:30

¿Quiéres usar código delphi en innosetup? Hasta donde yo lo he usado, eso no se puede hacer.

walterk. 06-09-2015 09:39:11

Cita:

Empezado por Casimiro Notevi (Mensaje 496327)
¿Quiéres usar código delphi en innosetup? Hasta donde yo lo he usado, eso no se puede hacer.

claro la idea es usar el codigo en inno setup, o mejor dicho lo necesito correr desde inno setup cuando realizo la instalacion de las areas. Tambien si conoces alguna forma diferente dime y pruebo porque la verdad esto me tiene preocupado.

Yo lo que hacia era:

[INI]
Filename: C:\Servicios\em\Scenery.CFG; Section: Area.1050; Key: Title; String: SA81 Puerto Cabra Corral; Flags: uninsdeleteentry uninsdeletesectionifempty;
Filename: C:\Servicios\em\Scenery.CFG; Section: Area.1050; Key: Local; String: {code:GetDirName}\Addon Scenery\SA81 Puerto Cabra Corral; Flags: uninsdeleteentry;
Filename: C:\Servicios\em\Scenery.CFG; Section: Area.1050; Key: Active; String: TRUE; Flags: uninsdeleteentry;
Filename: C:\Servicios\em\Scenery.CFG; Section: Area.1050; Key: Required; String: FALSE; Flags: uninsdeleteentry;
Filename: C:\Servicios\em\Scenery.CFG; Section: Area.1050; Key: Layer; String: 1050; Flags: uninsdeleteentry;

El problema empezo en que hay sucursales que no tiene la misma cantidad de areas y al yo ingresarles un numero de identificacion fija sobrescribia un area ya instalada y el software tira error.

Casimiro Noteví 06-09-2015 10:16:13

Cita:

Empezado por walterk. (Mensaje 496328)
... y el software tira error.

¿Qué error?
A ver, debes explicar EXACTAMENTE lo que quieres hacer, en todo su contexto, no somos adivinos, no vemos tu ordenador.
Usa también los conceptos correctos, porque si quieres ejecutar un programa delphi desde innosetup, eso no es "usar código delphi" en innosetup.


La franja horaria es GMT +2. Ahora son las 03:30:31.

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