Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Vos Contributions VBScript Discussion :

Lire/écrire une valeur de clé dans un fichier INI


Sujet :

Vos Contributions VBScript

  1. #1
    Rédacteur

    Lire/écrire une valeur de clé dans un fichier INI
    bonjour,

    compte-tenu des points communs entre le code d'écriture et de lecture
    j'ai finalement décidé d'écrire une routine regroupant les deux fonctionnalités

    donc le fichier test.ini à placer dans le répertoire "Mes Documents"
    Code ini :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    [UserHome]
    Name=
    Handy=21/10/2016 ;ceci est la clé recherchée
    WWW=
    [UserBusiness]
    Name=
    Handy=02/02/2015 ;pas celle-ci
    WWW=


    le code :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set wshell = CreateObject("WScript.Shell")
    Set oFile = fso.GetFile(wshell.SpecialFolders("MyDocuments") & "\test.ini")
    rep = WriteReadIni(oFile,"UserHome","WWW","nouvelle valeur de clé")
    Msgbox WriteReadIni(oFile,"UserHome","WWW",Null)
     
    Function WriteReadIni(oFile,section,key,value)
    ' écrit/lit la clé <key> de section <section> de l'objet fichier oFile avec la valeur <value> si lecture : value = Null 
    ' en écriture si la section et/ou la clé n'existent pas, elles seront créées
    ' en écriture renvoie toujours vrai, en lecture renvoie soit : la valeur de clé, une chaine vide en cas de clé vide ou Faux si la clé n'existe pas
    Dim oText,iniText,sectText,newSectText,keyText
    	' Initialisation des objets regexp
    	' peut être déplacé dans le code principal en cas d'appels successifs
    	Set reg = New RegExp
    	Set regSub = New RegExp
    	reg.IgnoreCase = True
    	regSub.IgnoreCase = True
    ' lecture du fichier ini et fermeture
    	Set oText = oFile.OpenAsTextStream(1,0)
    	iniText = oText.ReadAll
    	oText.Close
    	reg.Pattern = "\[" & section & "\]([^\[]+)":regSub.Pattern = "\b" & key & " *= *([^;\f\n\r\t\v]*)"
    	On Error Resume Next
    	If IsNull(value) Then   ' lecture clé
    		WriteReadIni = regSub.Execute(reg.Execute(iniText).Item(0).SubMatches(0)).Item(0).SubMatches(0)
    		If Err.Number = 5 then WriteReadIni = False
    	Else						' écriture clé
    		sectText = reg.Execute(iniText).Item(0).SubMatches(0)
    		If Err.Number = 5 Then ' section inconnue
    			iniText = iniText & vbCrLf & "[" & section & "]" & vbCrLf & key & "=" & value
    		Else
    			newSectText = regSub.Replace(sectText,key & "=" & value)
    			If newSectText = sectText Then
    				If Right(sectText,2) = vbCrLf Then keyText = key & "=" & value & vbCrLf Else keyText = vbCrLf & key & "=" & value & vbCrLf
    				newSectText = sectText & keyText
    			End If
    			iniText = reg.Replace(iniText,"[" & section & "]" & newSectText)
    		End If
    		' écriture du fichier ini mis à jour
    		Set oText = oFile.OpenAsTextStream(2,0)
    		oText.Write iniText
    		oText.Close
    		WriteReadIni = True
    	End If
    End Function

    Toute remarque sera la bienvenue avant de placer ce code dans la
    nomen omen, nemo non omen - Consultez la FAQ VBScript et les cours et tutoriels VBScript
    le plus terrible lorsqu'une voiture renverse un piéton, c'est que ce sont les freins qui hurlent. (ramón)
    pas de questions techniques par mp

  2. #2
    Rédacteur

    nouvelle version que j'espère définitive...
    nouveautés :
    - supporte les caractères [ et ] dans les valeurs de clés
    - élimine un gros bug (il était possible de créer des doublons de couple clé/valeur)
    - renvoie faux si la tentative d'écriture concerne un couple clé/valeur qui existe déjà

    merci de me signaler les bugs éventuels avant passage dans la

    le fichier test.ini à mettre dans le même répertoire que l'exemple
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    [H1]
    key1=val1
    key2=val2
    key3=[aga]
    [H2]
    key5=12  ;comment
    key6=HJUY
    key2=val2
    key2=val2
    [H3]
    key7=val5
    keyx=[KKK]
    key8=val6
    keyxy=]ghghg[s
    [H4]
    key9=klm
    key10=]ghghg[s
    [H5]
    ab=op
    KKName=ss


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set wshell = CreateObject("WScript.Shell")
    Set oFile = fso.GetFile("test.ini")
    Msgbox WriteReadIni(oFile,"H3","keyxy",Null)
    Msgbox WriteReadIni(oFile,"H5","ab",Null)
    Msgbox WriteReadIni(oFile,"H4","testtag","[zz[")
     
    Function WriteReadIni(oFile,section,key,value)
    ' *******************************************************************************************
    ' omen999 - mars 2018 v 1.1 - http://omen999.developpez.com/
    ' écrit/lit la clé <key> de section <section> de l'objet fichier oFile avec la valeur <value> si lecture : value = Null 
    ' en écriture si la section et/ou la clé n'existent pas, elles seront créées
    ' en écriture renvoie faux si le couple clé/valeur existait déjà sinon vrai
    ' en lecture renvoie soit : la valeur de clé, une chaine vide en cas de  clé vide ou Faux si la clé n'existe pas
    ' ********************************************************************************************
    Dim oText,iniText,sectText,newSectText,keyText
      ' Initialisation des objets regexp
      ' peut être déplacé dans le code principal en cas d'appels successifs
      Set reg = New RegExp
      Set regSub = New RegExp
      reg.MultiLine=True 'simplifie le pattern
      reg.IgnoreCase = True
      regSub.IgnoreCase = True
      Set oText = oFile.OpenAsTextStream(1,0)
      iniText = oText.ReadAll
      oText.Close
      reg.Pattern = "^\[" & section & "\]((.|\n[^\[])+)":regSub.Pattern = "\b" & key & " *= *([^;\f\n\r\t\v]*)"
      On Error Resume Next
      If IsNull(value) Then   ' lecture clé
        WriteReadIni = regSub.Execute(reg.Execute(iniText).Item(0).SubMatches(0)).Item(0).SubMatches(0)
        If Err.Number = 5 then WriteReadIni = False
      Else                                              ' écriture clé
        sectText = reg.Execute(iniText).Item(0).SubMatches(0)
        If Err.Number = 5 Then ' section inconnue
          iniText = iniText & vbCrLf & "[" & section & "]" & vbCrLf & key & "=" & value
        Else
          newSectText = regSub.Replace(sectText,key & "=" & value)
          If newSectText = sectText Then ' pas de remplacement constaté. soit le clé/valeur existe déjà soit c'est une nouvelle clé
            If regSub.Test(sectText) Then ' le couple clé/valeur existe déjà -> sortie
              WriteReadIni = False
              Exit Function	
            End If
            If Right(sectText,1) = vbCr Then keyText = key & "=" & value Else keyText = vbCrLf & key & "=" & value
            newSectText = sectText & keyText			
          End If
          iniText = reg.Replace(iniText,"[" & section & "]" & newSectText)
        End If
        Set oText = oFile.OpenAsTextStream(2,0)
        oText.Write iniText
        oText.Close
        WriteReadIni = True
      End If
    End Function
    nomen omen, nemo non omen - Consultez la FAQ VBScript et les cours et tutoriels VBScript
    le plus terrible lorsqu'une voiture renverse un piéton, c'est que ce sont les freins qui hurlent. (ramón)
    pas de questions techniques par mp

  3. #3
    Membre du Club
    Salut merci pour ce code je l'ai mis dans mon code
    malheureusement j'ai remarqué quelques bugs
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    [CONFIG]
    MAJ=1.0.7
    OK=1
    MUSIC=C:\Users\MOI\Desktop
    [Logiciel]

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    WriteReadIni (oFile,"CONFIG","WEBHOOKS","KEY2")

    Qui de temps en temps me l'écrit après la balise Logiciel ou qui ne retourne pas a la ligne ou qui colle la balise [Logiciel] a la fin

    Mais je te contacte surtout pour savoir comment modifier une key ou valeur si elle existe déja ? (voir supprimé key ou valeur si possible)


  4. #4
    Rédacteur

    bonjour,

    effectivement la v2 a introduit une régression...
    la v1 ne présente pas ce bug et insère ta clé correctement
    si tu n'essaies pas d'écrire un couple clé/valeur qui existe déjà
    et que tu n'a pas besoin de gérer des valeurs contenant des crochets
    la v1 fera l'affaire....
    j'ai également oublié de préciser que le code n'est pas compatible avec les
    fichiers .INI présentant un BOM. j'en ai une version compatible BOM mais elle
    n'est pas assez générique pour être publiée ici.


    pour modifier la valeur d'une clé existante, il suffit de l'écrire avec une valeur différente
    ex :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    WriteReadIni oFile,"CONFIG","WEBHOOKS","KEY3"


    en revanche modifier une clé revient en réalité à la supprimer et à en écrire une nouvelle
    mon code ne prévoyait pas la suppression de clé
    je vais voir si je peux facilement la rajouter tout en supprimant le bug
    nomen omen, nemo non omen - Consultez la FAQ VBScript et les cours et tutoriels VBScript
    le plus terrible lorsqu'une voiture renverse un piéton, c'est que ce sont les freins qui hurlent. (ramón)
    pas de questions techniques par mp

  5. ###raw>post.musername###
    Rédacteur
    mon code ne prévoyait pas la suppression de clé
    je vais voir si je peux facilement la rajouter tout en supprimant le bug
    ..presque deux ans plus tard et avec un peu de confinement méditatif voici la version 1.2 que j'espère définitive

    changelog 1.1 - > 1.2
    - bug insertion des nouvelles clés/valeurs corrigé
    - support des caractères = et ; (échappé) dans les valeurs de clés
    - ajout des options de suppression de section et de clé

    syntaxe conforme au format de l'API ini Windows sauf exception (*)
    - accepte les lignes blanches
    - pas sensible à la casse
    - support des commentaires ligne entière
    - pas d'espace dans le nom de clé ou en début de ligne
    - pas de caractère = dans le nom de clé
    - * support des commentaires de fin de ligne : implique que le point virgule n'est pas accepté dans les valeurs de clé sauf échappement (cf infra)
    - * les espaces de fin de valeur sont conservés
    - * pas de suppression auto des quotes de valeurs de clé ("')
    - * support de l'échappement du caractère ; dans les valeurs de clé : \;

    le code est volontairement très commenté et peut être testé avec le fichier test.ini qui suit

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ofi = fso.GetFile("test.ini")
    MsgBox WriteReadIni(ofi,"A","A1",Null)
    MsgBox WriteReadIni(ofi,"b","b1",Null)
    'MsgBox WriteReadIni(ofi,"c",Empty,Empty)  ' supprime la section [C]
     
    ' ********************************************************************************************************************
    ' omen999 - avril 2020 v 1.2 - https://omen999.developpez.com/
    '  WriteReadIni(ofi, section, key, value)
    ' 1. lit la valeur de clé <key> de section <section> de l'objet fichier ofi
    ' 2. écrit la clé <key> de section <section> de l'objet fichier ofi avec la valeur <value>
    ' 3. supprime la section <section> et/ou la clé <key> de l'objet fichier ofi
    ' lecture : value = Null 
    ' écriture : si la section et/ou la clé n'existent pas, elles seront créées
    ' suppression clé/valeur : value = Empty 
    ' suppression section entière : key et value = Empty 
    '
    ' valeur renvoyée :
    ' lecture : la valeur de clé, une chaine vide en cas de clé sans valeur ou faux si la clé n'existait pas
    ' écriture : faux si le couple clé/valeur existait déjà sinon vrai
    ' suppression : faux si la section ou clé à supprimer n'existait pas ou vrai en cas de succès
    ' ********************************************************************************************************************
    Function WriteReadIni(ofi, section, key, value)
      Dim reg, regsub, stext, initext, regmatch, newdata
      ' initialisation des objets regexp, peut être déplacé dans le code principal en cas d'appels successifs
      Set reg = New RegExp : Set regsub = New RegExp
      reg.IgnoreCase = True : regsub.IgnoreCase = True
     
      WriteReadIni = False ' valeur par défaut de la fonction
      ' lecture intégrale du fichier ini
      Set stext = ofi.OpenAsTextStream(1,0)
      initext = stext.ReadAll
      stext.Close
      ' definition du pattern
      ' reg va renvoyer le contenu de la section entière avec toutes ses clés
      ' 1ère occurrence car .Global est laissé à False donc toute section suivante portant le même libellé sera ignorée 
      ' le début de la capture est défini par le nom de section placé en début de ligne entre crochets
      ' [nom de section] est placé dans une 1ère sous-correspondance (index 0) : (^\[" & section & "\])
      ' la suite est définie comme tous les caractères suivants le crochet fermant jusqu'à
      ' un saut de ligne suivi d'un crochet ouvrant ou de la fin de chaine avec ou sans saut de ligne
      ' le tout également placé dans une 2ème sous-correspondance (index 1) : ((.|\n[^\[])*\n?)
      ' l'insertion de toute clé/valeur nouvelle se fera à la jonction entre les sous-correspondances d'index 0 et 1
      reg.MultiLine = True ' évite la capture du début de ligne
      reg.Pattern = "(^\[" & section & "\])((.|\n[^\[])*\n?)"   
      ' une 2ème expression régulière (regsub) est appliquée au résultat renvoyé par reg
      ' elle renvoie la 1ère occurrence de la valeur de clé recherchée (.Global=False)
      ' definition du pattern
      ' le début de la capture est défini par le nom de clé éventuellement précédé d'un retour ligne, non précédé
      ' d'un espace ou d'un ; suivi d'un = éventuellement entouré d'espaces
      ' la sous-correspondance renvoie la valeur de clé (tous les caractères non spéciaux y compris = avant un éventuel ; non échappé)
      regsub.Pattern = "(\r\n)?[^; \n]*" & Trim(key) & " *= *((\\;|=|[^;\f\n\r\t\v])*)"
      On Error Resume Next
      Set regmatch = reg.Execute(initext)
      If IsNull(value) Then   ' lecture clé en une seule ligne
        WriteReadIni = Replace(regsub.Execute(regmatch(0))(0).SubMatches(1),"\;",";")
      Else                    ' écriture/suppression section et/ou clé/valeur -> maj d'iniText
        ' suppression section ou clé/valeur
        If IsEmpty(value) Then
          If Err.Number > 0 Then Exit Function
          regsub.Pattern = "(\r\n)?[^; \n]*" & key & " *= *((=|[^\f\n\r\t\v])*)" ' maj pattern capturant également les commentaires de fin de ligne
          ' suppression section existante
          If IsEmpty(key) Then
            iniText = reg.Replace(initext,"")
          Else ' suppression clé/valeur
      	If regsub.Test(regmatch(0)) Then initext = reg.Replace(initext,regsub.Replace(regmatch(0),"")) Else Exit Function
          End If
        Else	
          ' ajout section, clé/valeur ou modif valeur de clé
          If key = "" And value <> "" Then Exit Function   ' pas de valeur sans clé
          If key <> "" Then key = key & "="
          newdata = vbCrLf & key & value
          If Err.Number = 5 Then ' section inconnue : elle est ajoutée en fin de fichier avec son éventuel couple clé/valeur  		
            initext = initext & vbCrLf & "[" & section & "]" & newdata 
          Else ' la section existe, si clé existante -> maj sinon ajoutée au 1er rang de la section
            If regsub.Test(regmatch(0)) Then initext = reg.Replace(initext,regsub.Replace(regmatch(0),newdata)) Else initext =_
                                                       reg.Replace(initext,regmatch(0).SubMatches(0) & newdata & regmatch(0).SubMatches(1))
          End If
        End If
        ' iniText maj sauvegarde du fichier ini
        Set stext = ofi.OpenAsTextStream(2,0)
        stext.Write initext
        stext.Close
        WriteReadIni = True
      End If
    End Function

    le fichier test.ini :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [A]
    A1= ceci est point-virgule \;.    ;comment1
     
    [B]
    B1= b=[value]   ;comment2
    B2=
    [C]
    CName=test
    CSurname = [z]z[
    [D]
      2  0

###raw>template_hook.ano_emploi###