begin process at 2010 09 03 22:13:04
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Divers

 > GESTIONNAIRE DE FICHIERS DE CONFIGURATION

GESTIONNAIRE DE FICHIERS DE CONFIGURATION


 Information sur la source

Note :
9 / 10 - par 2 personnes
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Divers Classé sous :xmldocument, treeview, valuelisteditor, configuration, dragdrop Niveau :Initié Date de création :19/01/2007 Date de mise à jour :24/07/2007 08:38:20 Vu / téléchargé :5 411 / 924

Auteur : sylvunix

Ecrire un message privé
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
J'ai remarqué lorsqu'une application assez conséquente était développée, que je passais un temps conséquent à écrire les procédures de lecture et d'enregistrement des fichiers de configuration.

Cette partie est pour moi l'une des moins intéressantes du projet car, d'un point de vue intellectuel, elle n'apporte absolument rien. Lassé de perdre mon temps, j'ai craqué lors de l'écriture d'un logiciel dont le nombre de fichiers de configuration était très important.

Je vous propose donc le fruit de mes réflexions.

L'idée est de représenter tous les paramètres d'une configuration sous la forme d'une arborescence d'objets. Chaque niveau de l'arborescence est représenté par un objet TConfiguration dans lequel il est également possible de stocker des paramètres.

Prenons un exemple de configuration.

Notre application fictive permet de transférer automatiquement le contenu de répertoires locaux vers un serveur en ftp. Nos informations de configuration seront les informations relatives à la connexion au serveur et l'arborescence à transférer.

        -- configuration
         +-- serveurftp
         +-- arborescence
         ! +-- dossier
         ! +-- dossier
         +-- options

On positionnera dans l'objet serveurftp, l'adresseip, le nom du compte, le mot de passe (qui sera crypté dans le fichier), le numéro de port et le répertoire par défaut.

L'objet arborescence contiendra quant à elle la liste des dossiers à transférer. Chaque dossier étant lui-même un objet qui pourra contenir des paramètres.

Le dernier objet sera les options avec par exemple comme paramètre le nom du journal de traces.

Cet exemple se traduirait comme suit en Delphi :

uses TSxConfiguration;

...

var Configuration, ServeurFtp, Arborescence, Options: TSxConfiguration;

...

  // Création de l'objet principal
  Configuration := TSxConfiguration.Create;
  Configuration.PrivateKey := 'delphifr';

  // Création de l'objet serveur et inscription des paramètres
  ServeurFtp := TSxConfiguration.Create(Configration);
  ServeurFtp.Name := 'serveurftp';
  ServeurFtp.addValue('adresse','198.162.0.1');
  ServeurFtp.addValue('compte','admin');
  ServeurFtp.addValue('motdepasse','tordu',true);
  ServeurFtp.addValue('port',21);
  ...
  
  // Création de l'arborescence et de la liste des dossiers
  Arborescence := TSxConfiguration.Create(Configration);
  Arborescence.Name := 'arborescence';
  for ...
    with TSxConfiguration.Create(Arborescence) do addValue('dossier', ...);

  // Création de l'objet options et inscription des paramètres
  Options := TSxConfiguration.Create(Configration);
  Options.Name := 'options';
  Options.addValue('traces',true);
  Options.addValue('journal','C:\Mon soft\log\journal.txt');

  // Et la cerise sur le gâteau : la sauvegarde
  Configuration.SaveToFile('C:\Mon soft\cfg\configuration.cfg');

Le code permettant la relecture du fichier de configuration est le suivant.

  // Création de l'objet principal
  Configuration := TSxConfiguration.Create;

  // Lecture du fichier de configuration
  Configuration.LoadFromToFile('C:\Mon soft\cfg\configuration.cfg');

  // Extrait les objets
  ServeurFtp := Configuration.Search('serveurftp');
  Arborescence := Configuration.Search('arborescence');
  Options := Configuration.Search('options');
  
Pour réaliser cet exemple, seule l'unité Configuration.pas est nécessaire. Tous les détails concernant cette unité sont indiqués dans l'entête.

La seconde partie du projet que je vous fais partager est un browser de configuration appelé TExplorateur. Il permet de représenter la configuration au travers d'un treeview et surtout de la manipuler.

Consultez également l'entête du fichier qui vous en apprendra beaucoup plus.

Enfin pour terminer, j'ai réalisé un Gestionnaire de Fichiers de Configuration capable de créer et de relire tous vos fichiers de configuration. Il est livré à titre indicatif.



 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

24 janvier 2007 16:42:36 :
Bonjour comme promis une mise à tenant compte des remarques très constructives de f0xi. Un bug relatif au copier/coller a été corrigé en même temps.
02 février 2007 12:42:59 :
Une nouvelle version qui intègre la possibilité de stocker des données cryptées comme par exemple les mots de passe. La classe TConfiguration dispose d'un nouvel attribut, PrivateKey, dans lequel on spécifie la clef privée à utiliser pour le cryptage et le décryptage. La méthode AddValue dispose d'un second prototype qui permet de signaler si la donnée doit être cryptée ou non.
22 mars 2007 15:24:45 :
Nouvelle version intégrant les (nombreuses) remarques (très constructives) de Loda. Il s'agit essentiellement de corrections sur la gestion mémoire et optimisation du code.
29 juin 2007 14:50:53 :
Encore une nouvelle version suite à des propositions d'optimisation et à des maladresses dans la gestion de la mémoire. Correction d'un bug important qui apparaissait lors du drag'n drop.
24 juillet 2007 08:38:20 :
Corrections dans la présentation du projet

 Sources de la même categorie

Source avec Zip ARBRES N-ARIES par Kagemaru
Source avec Zip Source avec une capture UN LOGICIEL POUR ÊTRE AVERTI QUAND UN BUS ARRIVE par pseudomino
Source avec Zip ALPHA DE CRONBACH (INDICE UTILISÉ EN PSYCHO) par fredelem
Source avec Zip Source avec une capture SIMULATION D'UN VIEUX PC par Debiars
Source avec Zip Source avec une capture NDKEYGEN (GÉNERER LES SERIAL NUMMER) par diglas

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture FICLOCK : LOCKEZ LES FICHIERS par JulioDelphi
Source avec Zip Source avec une capture BLOODSAVER (LE PLUS GORE DES SCREENSAVERS) par Bacterius
Source avec Zip Source avec une capture PETIT UTILITAIRE TREEVIEW par Bacterius
Source avec Zip RÉGLE À CALCULS ET IMAGE TRANSPARANTE PARTIELLEMENT par yvessimon
Source avec Zip Source avec une capture INSTALLATEUR DE PROGRAMMES (V2) par pepitto

Commentaires et avis

Commentaire de Loda le 19/01/2007 09:20:57

salut,

ça m'as l'air très intéressant.... Je dl le code quand j'aurais un moment.

merci pour ça...

A+

Commentaire de f0xi le 19/01/2007 10:42:35 administrateur CS

hey, ça m'a l'air pas mal du tout ça.

par contre je vois quelques erreurs.

du genre, on appel pas Destroy directement pour detruire une instance d'objet mais Free!
cela evite certaines erreur car Free fait quelques verifications avant de d'appeler Destroy.


plutot que de faire :
Reponse := MessageDlg('Enregistrer les modifications dans le fichier de configuration ?', mtInformation, [mbYes,mbNo,mbCancel], 0);
if Reponse = mrCancel then exit;
if Reponse = mrYes then menuEnregistrerSousClick(Sender);

fait plutot :

case MessageDlg('Enregistrer les modifications dans le fichier de configuration ?', mtInformation, [mbYes,mbNo,mbCancel], 0) of
   mrCancel : exit;
   mrYes    : menuEnregistrerSousClick(Sender);
end;

case MessageDlg('Enregistrer les modifications dans le fichier de configuration ?', mtInformation, [mbYes,mbNo,mbCancel], 0) of
  mrCancel : CanClose := False;
  mrYes    : menuEnregistrerSousClick(Sender);
end;


pour la classe TConfiguration tu ecris :

  // Génère un identifiant unique. La méthode est archaïque mais efficace
Randomize;
Tirage := Random(2147483646);
FId := RightStr('00000000'+IntToStr(Tirage),8);
Tirage := Random(2147483646);
FId := FId+RightStr('00000000'+IntToStr(Tirage),8);

appel randomize dans la zone Initialization de l'unité c'est mieux!

ensuite tu peu faire pour generer un identifiant unique aleatoire :

unit GenID;

interface

uses
  Windows, SysUtils, Classes;

type
  TID = int64;

function IDToHex(const ID : TID) : string;
function GenerateID(const FlushIDTable : boolean = false) : TID;

implementation

var
  __IDTABLE : TStringList;

function IDToHex(const ID : TID) : string;
var
  pB : ^byte;
  pR : PChar;
  N  : integer;
const
  Dig : array[$0..$F] of char = '0132456789ABCDEF';
begin
  SetLength(Result, 16);
  pB := @ID;
  pR := PChar(Result);
  inc(pB,7);
  for N := 0 to 7 do begin
      pR[0] := Dig[pB^ shr 4];
      pR[1] := Dig[pB^ and $F];
      inc(pR,2);
      dec(pB);
  end;
end;

function GenerateID(const FlushIDTable : boolean = false) : TID;
type
  QuadWord = array[0..3] of word;
  ArrChar  = array[0..7] of char;
var
  QW1,QW2 : QuadWord;
  ID      : TID;
  pB      : ^byte;
  N       : integer;
  S       : ArrChar;
label
  Generate;
begin
  // si on ecrase la table des ID on renvois 0 et on sort;
  if FlushIDTable then begin
     result := 0;
     __IDTABLE.Clear;
     exit;
  end;

  Generate :
    // initialisation
    QW1 := QuadWord( $5C951D1DE74FCC32 xor Random(High(int64)) );
    QW2 := QuadWord( $0A5628FAD43E96CB xor Random(High(int64)) );

    // un algorithme simple de chiffrement
    QW2[0] := word( (QW2[3] shl 13) or (QW1[0] shr  3) );
    QW1[3] := word( (QW1[2] shl 15) or (QW2[3] shr  1) );
    QW2[1] := word( (QW2[0] shl  9) or (QW1[1] shr  7) );
    QW1[2] := word( (QW1[1] shl 12) or (QW2[2] shr  4) );
    QW2[2] := word( (QW2[1] shl  5) or (QW1[2] shr 11) );
    QW1[1] := word( (QW1[0] shl  8) or (QW2[1] shr  8) );
    QW2[3] := word( (QW2[2] shl  2) or (QW1[3] shr 14) );
    QW1[0] := word( (QW1[3] shl  4) or (QW2[0] shr 12) );

    // finalisation
    ID := TID(QW1) xor TID(QW2);

    // suppression des 00
    pB := @ID;
    for N := 0 to 7 do begin
        if pB^ <= $0F then
           pB^ := $0F+(random($E9)+1);
        inc(pB);
    end;

    // insertion de S
    S := ArrChar(ID);

    // verification des doublons
    if __IDTABLE.IndexOf(string(S)) = -1 then begin
       // ajout
       __IDTABLE.Add(string(S));
       // retour
       result := ID;
       // sortie
       exit;
    end else
       // sinon on regenere un ID
       goto Generate;
end;

initialization
  // initialisation des nombres aleatoire
  Randomize;

  // creatiob de la table des ID pour garantire la generation
  // d'ID unique durant la session.
  __IDTABLE            := TStringList.Create;
  __IDTABLE.Sorted     := true;
  __IDTABLE.Duplicates := dupIgnore;

finalization
  // liberation de la table des ID
  __IDTABLE.Free;

end.


sinon le reste semble pas mal, j'ai pas trop fouiner mais tout me semble correct.

voila.

Commentaire de sylvunix le 19/01/2007 12:05:50

Merci f0xi pour tes critiques (constructives).

Sur la génération des TId, je savais que j'étais un peu léger mais cela fonctionnant j'ai oublié de remettre cette portion de code en question.

Je suis intrigué par le choix de tes valeurs $5C951D1DE74FCC32 et $0A5628FAD43E96CB  dans les lignes :

    QW1 := QuadWord( $5C951D1DE74FCC32 xor Random(High(int64)) );
    QW2 := QuadWord( $0A5628FAD43E96CB xor Random(High(int64)) );

Cela correspond-il à un délire de hamster sur le clavier ou y a-t-il une astuce qui m'aurait échappé ?

Je teste tout cela et je déposerai une mise à jour la semaine prochaine ...

Commentaire de tigris1 le 19/01/2007 14:05:56

Très intéressant, très utile, très pratique et qui peut donner des idées pour une utilisation élargie à d'autres besoins que la configuration.

Le code semble bien écrit, bien lisible et très commenté.

Merci pour ce joli travail dont je ne manquerai pas de m'en inspiré à l'occasion.

tigris1

Commentaire de f0xi le 19/01/2007 15:48:35 administrateur CS

hi!

les deux valeurs pour QW1 et QW2 sont des valeurs qui sont choisis pour avoir un certain nombre de bit a 0 et a 1 a peu prés equilibré, avec suffisement de valeur correspondante et decalé par rapport a QW1 et QW2.

si on applique un QW1 XOR QW2 cela nous donneras une valeur comprise entre de High(cardinal) et  high(int64)

QW1 = 01011100 10010101 00011101 00011101 11100111 01001111 11001100 00110010
QW2 = 00001010 01010110 00101000 11111010 11010100 00111110 10010110 11001011
XOR = 01010110 11000011 00110101 11100111 00110011 01110001 01011010 11111001
en gros ça nous donne une valeur qui fait :
6 blocs de 4 zero et 4 un
2 bloc de 2 zero et 6 un
ce qui nous donne une bonne base a vide pour passer dans le hacheur par la suite.

IDTABLE nous assure l'unicitée de l'ID qui en decoule, mais les collisions seront plus rare qu'avec un simple random, ce qui nous donne un generateur assé performant et fiable.

c'est le principe des hash, une simple modification de 1 bit donne une clef differente.

Commentaire de f0xi le 19/01/2007 16:09:02 administrateur CS

mais a un moment, je viens de penser que ça faisait beaucoup de travail pour pas grand chose en fait.

car si tu veux tu as beaucoup plus cours pour faire une config.

en gros ça donne :


type
  TConfiguration = record
     UnBooleen  : boolean;
     UneChaine  : string[64];
     UnFlottant : single;
     UnEntier   : integer;
  end;

procedure SaveConfigToFile(const Config : TConfiguration; const FileName : string);
var TFS : TFileStream;
begin
  TFS := TFileStream.Create(FileName, fmCreate);
  try
    TFS.WriteBuffer(Config, SizeOf(TConfiguration));
  finally
    TFS.Free;
  end;
end;

procedure LoadConfigFromFile(var Config : TConfiguration; const FileName : string);
var TFS : TFileStream;
begin
  TFS := TFileStream.Create(FileName, fmRead);
  try
    TFS.ReadBuffer(Config, SizeOf(TConfiguration));
  finally
    TFS.Free;
  end;
end;

et hop, tu l'as ta config ... :)
par contre, interdiction d'aller modifier le fichier de config directement dans le bloc note.

Commentaire de sylvunix le 19/01/2007 17:48:57

f0xi,

Chapeau pour ta génération de TId, je n'avais même pas envisagé d'aller si loin.

Cependant, ta méthode de sauvegarde ne fonctionnera pas avec une arborescence d'objets, comme TConfiguration, auxquels sont attachés des listes de variables.

De plus, mes fichiers sont actuellement sauvegardés au format xml avec une structure propre donc effectivement réexploitables par d'autres logiciels.

Commentaire de f0xi le 20/01/2007 03:21:10 administrateur CS

ouai c'est sur que le truc pourris des record pour les config c'est carrement pas exploitable a sec par d'autre logiciel...

Commentaire de f0xi le 24/01/2007 20:20:28 administrateur CS


petite modif qu'on peu appliquer a GenerateID :
(on a pas besoin d'une locale Tid puisqu'on as deja result)

function GenerateId : TId;
type
  QuadWord = array[0..3] of word;
  ArrChar = array[0..7] of char;
var
  QW1,QW2 : QuadWord;
  Uid     : int64;
  pB      : ^byte;
  N       : integer;
begin
  repeat
    // Initialisation
    QW1 := QuadWord( $5C951D1DE74FCC32 xor Random(High(int64)) );
    QW2 := QuadWord( $0A5628FAD43E96CB xor Random(High(int64)) );

    // Un algorithme simple de chiffrement
    QW2[0] := word( (QW2[3] shl 13) or (QW1[0] shr 3) );
    QW1[3] := word( (QW1[2] shl 15) or (QW2[3] shr 1) );
    QW2[1] := word( (QW2[0] shl 9) or (QW1[1] shr 7) );
    QW1[2] := word( (QW1[1] shl 12) or (QW2[2] shr 4) );
    QW2[2] := word( (QW2[1] shl 5) or (QW1[2] shr 11) );
    QW1[1] := word( (QW1[0] shl 8) or (QW2[1] shr 8) );
    QW2[3] := word( (QW2[2] shl 2) or (QW1[3] shr 14) );
    QW1[0] := word( (QW1[3] shl 4) or (QW2[0] shr 12) );

    // Finalisation
    Uid := int64(QW1) xor int64(QW2);

    // Suppression des 00
    pB := @Uid;
    for N := 0 to 7 do begin
        if pB^ <= $0F then pB^ := $0F+(random($E9)+1);
        inc(pB);
    end;

    // Conversion du résultat en TId
    result := IntToId(Uid);

    // Si l'unicité du TId est vérifiée, on le mémorise en on quitte
    if IdTable.IndexOf(result) = -1 then begin
       IdTable.Add(Result);
       Exit;
    end;

  // Répéter l'opération jusqu'à ce qu'un TId unique soit trouvé
  until True;
end;

Commentaire de sylvunix le 24/01/2007 21:39:06

f0xi,

Moi qui me disait perfectionniste, je pense que je suis largement battu ! Mais je prends note ...

J'aimerais faire évoluer cette classe en offrant la possibilité de stocker des données cryptées, comme un mot de passe par exemple, en utilisant un algorithme DES. Il y aurait un attribut ClefPrivee dans la classe et on pourrait utiliser le TId comme clef publique.

Qu'en penses-tu ?

Commentaire de ezekiel62 le 23/07/2008 14:13:28

Ce projet semble fort interessant, mais ne se compile pas sous Delphi5...
erf...
Vais essayer d'étudier la source quand même
beau boulot...

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Image de fond dans un TreeView [ par Valérie ] Bonjour, J'utilise une application DELPHI6 CLX et je n'aarive pas à avoir une image de fond dans mon TreeView. L'événement OnPaint n'existe pas. Si ListView, TreeView ! INDEX! [ par rtfm ] Salut ma petit gang de delphinologue ;pJ'ai un petit probleme.. J'aurais besoin d'une manière de stocker la crée primaire de la string que j'ajoute a TreeView [ par XJapan ] Salut à tous !Je voudrais savoir si il a possibilite de changer le contenue d'un TreeView par click sur un bouton. J'ai du mal a me depatouiller avec ListView-TreeView [ par Gysmo ] Salut,Ou puis-je trouver un exemple sur la sychro ListView-TreeView, a la maniere de ShellListView-ShellTreeView?Merci. PB ListView [ par Gysmo ] Voila j'ai un ListView sinchro avec un TreeView.Le prob est ke kan je suis en mode vsReport, j'ai des info type taille du fichier, ben si je change de ValueListEditor [ par ak47 ] salut!Je voudrais pouvoir rajouter une ligne à une ValueListEditor. Pour cela, je suppose qu'il faut que j'utilise la fonction ValueListeditor1.Insert Create Form explication [ par Bruto ] Salut,voila comme je débute en Delphi ( migration VB oblige ), je rencontre qq prob's.Explication ( ce que je voudrais ) :Mon programme se lance et pa Application MDI et Drag and drop [ par zorg63 ] Bonjour,mon problème: J'ai créé une application MDI avec des form mdichild contenant un treeview et une listview. Je veux pouvoir faire du drag and dr Pb sur TreeView [ par ogizmo ] Bonjour à tous,Lorsque je valorise la propriété root d'un treeview sur mon appli, seul le premier répertoire sur la racine est affichée :root = 'C:\wi


Nos sponsors


Sondage...

CalendriCode

Septembre 2010
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
27282930   

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,764 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales