IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Scripts/Batch Discussion :

Quelques notions importantes sur la commande interne 'SET'


Sujet :

Scripts/Batch

  1. #1
    Membre Expert
    Avatar de I'm_HERE
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 013
    Par défaut Quelques notions importantes sur la commande interne 'SET'
    salut,

    ceci n'est pas une introduction sur la notion des variables..

    ce petit topic peut être ajouter aux HOWTO précédents variables1/2


    SET

    1/ Assignation par référence

    le scripting de command NT ne supporte pas nativement le référencement de variables, on peux contourner ce problème en utilisant une petite astuce qui s'appuie sur le comportement de l'interpreteur vis à vis de l'expansion des variables.
    cette assignation par référence signifie que les deux variables pointent vers le même conteneur de donnée.
    Les références sont un moyen d'accéder au contenu d'une même variable en utilisant plusieurs noms. Les références ne sont pas comme des pointeurs en C, vous ne pouvez pas effectuer d'opération arithmétique sur celles-ci.

    1/a/ comment créer une réference:

    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
    @echo off
    setlocal DisableDelayedExpansion
    
    set a=3
    set b=!a!
    
    setlocal EnableDelayedExpansion
    
    echo %a%   % affiche 3 %
    echo %b%   % affiche 3 %
    
    set a=4    % change la variable a %
    
    
    echo %a%   % affiche 4 %
    echo %b%   % affiche 4 aussi,car 'b' est une référence à 'a' qui a été changée %
    
    pause
    1/b/ comment créer une reference de reference:

    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
    @echo off
    setlocal DisableDelayedExpansion
    
    set a=3
    set b=!a! % on créer une réference qui pointe vers 'a' %
    set c=!b! % on créer une référence qui pointe vers 'b' %
    
    setlocal EnableDelayedExpansion
    
    
    set a=4
    
    echo %a%                % affiche 4 %
    echo %b%                % affiche 4 %
    cmd /v /c echo %c%      % affiche 4, on force l'expansion avec un sous shell %
    
    pause
    un autre 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
    @echo off
    setlocal DisableDelayedExpansion
    
    set a=1
    set c=2
    
    set b=!a!
    set a=!c!
    
    setlocal EnableDelayedExpansion
    
    % affiche 2   %    echo %a%  
    % affiche 2   %    cmd /v /c echo %b%
    
    set a=18
    
    % affiche 18 %     echo %a% 
    % affiche 18 %     cmd /v /c echo %b%
    
    pause


    1/c/ comment savoir si une variable est une référence ou pas:
    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
    @echo off
    setlocal DisableDelayedExpansion
    
    set a=3
    set b=!a!  % set b=K % 
    
    setlocal EnableDelayedExpansion
    
    echo %a% 
    echo %b%
    
    set a=4 
    
    
    echo %a% 
    echo %b% 
    
    if "!b!" NEQ "%b%" (echo REF) else (echo NO-REF)
    
    pause

    2/ création d'un caractère LineFeed:

    la commande SET ne permet pas seulement de créer de simple chaîne de caractères mais aussi elle permet d'injecter dans la variable des caractères spéciaux telque le caractère LF (retour à la ligne), pour ce faire on a aux moins deux possibilité

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @echo off
    setlocal EnableDelayedExpansion
    
    
    (Set \n=^ 
    
    )
    echo a!\n!b!\n!c
    
    pause

    ou bien en combinant l'effet de pause avec set/P:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @echo off
    
    :)
    setlocal enabledelayedexpansion
    >nul,(pause&set /p LF=&pause&set /p LF=)<%0
    set LF=!LF:~0,1!
    
    echo a!LF!b!LF!c
    
    pause


    SET/P


    l'utilisation de la commande SET avec le commutateur /P permet de lire une ligne d'entrée à partir de la console. Vous pouvez l'utiliser pour inviter un utilisateur à entrer du contenu.

    1/ simplification syntaxique

    beaucoup de batcheurs utilisent cette syntaxe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo entrez le nom du serveur
    set /p server=
    on peux la simplifier ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set /p server=entrez le nom du serveur

    2/ lire une/plusieurs ligne(s)

    2/a/ lire une lgne:

    on peux lire la première la première ligne d'un fichier et la stocker dans une variable:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    set /p ligne1=<c:\scripts\cmd\f1.txt
    echo %ligne1%
    2/b/ exemple pratique:

    afficher la longeur d'une chaine renvoyer par l'utilisateur ou un autre programme par le pipeline

    length.cmd
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @echo off
    set len=
    set /p len=
    
    for /f "skip=1 delims=:" %%i in ('"(set len&echo()|findstr /o ".*""') do set/a n=%%i-6
    echo str: %len% len: %n% 
    exit /b
    
    
    echo hello world| length.cmd
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str: hello world len: 11
    2/b/ lire plusieurs lignes:

    on peux aussi lire plusieurs lignes en chaînant des set/p:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    (
       set /p ligne1=
       set /p ligne2=
       set /p ligne3=
    
    ) < c:\scripts\cmd\f1.txt
    
    echo %ligne3%
    echo %ligne2%
    echo %ligne1%
    2/c/ exemple pratique:

    combiner le contenu de deux fichiers

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @echo off
    Setlocal EnableExtensions DisableDelayedExpansion
    
    ( 
      for /f "delims=" %%a in (f1.txt) do (
        set /p ligne=
        setlocal enabledelayedexpansion
          echo %%a - !ligne!
        endlocal
      )
    ) < f2.txt
    
    endlocal

    sortie:
    3/ conserver/supprimer les espaces du debut d'une ligne:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    (set spc=          developpez.com)
    set/p "=%spc%"<nul
    echo(
    set/p ="%spc%"<nul

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
              developpez.com
    developpez.com

    On peux utiliser cette technique pour supprimer les espaces au debut
    d'une chaine de caractères on pourra utiliser cette technique par exemple dans une fonction PadLeft

    4/ ligne sans CRLF:

    il est possible d'utiliser SET/P pour avoir une chaine sans CRLF

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    set /p=developpez.<nul
    set /p=com<nul
    
    > developpez.com

    SET/A

    1/ renvoyer un résultat en une seule opération

    on peux utiliser SET/A sans utiliser de variable:


    2/ opérateur combinés:

    En plus du simple opérateur d'assignation, il existe des "opérateurs combinés" pour tous les opérateurs arithmétiques

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    > set /? | findstr "+="


    3/ Assignation multiple

    si on a plusieurs variable qui partage le même contenu on peux simplifier l'assignation en utilisant une syntaxe spéciale


    :: avant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    set /A i=5
    set /A j=5
    set /A k=5
    :: maintenant

    3/ decimal/ octal/ hexadecimal

    SET/A supporte nativement les nombres octales et hexadecimal:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    set /a hex=0xA * 0xB
    
    set /a oct=015
    on pourra par exemple créer une simple fonction HexaToDec/OctToDec pour convertir entre les différents bases

    4/ plus besoin d'activer l'expansion retardé de variables:

    on peux utiliser les variables numériques dans des block de codes sans activer l'expansion retardé de variables, en utilisant cette syntaxe

    :: le problème
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      @echo off
      (
        set h=10
        set w=20
        set /a a=%h% * %w%
      )
      echo %a%

    :: activer l'expansion retardé des variables

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @echo off
    setlocal enabledelayedexpansion
    
      (
        set h=10
        set w=20
        set /a a=!h! * !w!
      )
    echo %a%
    :: sans activer l'expansion retardé des variables:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    @echo off
    
      (
        set h=10
        set w=20
        set /a a=h * w
      )
    echo %a%
    5/ injecter la valeur d'une equation dans une autre variable:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    set a=60,b=20
    for /f %%x in ('"set /a (a-b)/4"') do set c=%%x

    6/ utilisation du modulo:


    l'opérateur modulo est très pratique en scripting, son utilisation la plus courante est dans les traitement et formatge de donnée par alternance, par exemple:
    "mettre une ligne vide pour chaque n lignes"
    "afficher les ligne paire/impaire d'un fichier"
    ..etc

    mais faite attention de ne pas utiliser le modulo avec de grands nombres:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set /a x=3333333333 % 3
    va retouner "-1" au lieu de "0"

    6/a/ exemple pratique:

    traitement sur chaque N ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    f1.txt
    
    ligne 1
    ligne 2
    ligne 3
    ligne 4
    ligne 5
    ligne 6
    ligne 7
    ligne 8
    ligne 9
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @echo off
    
    set /a chaque_N_ligne=2
    
    for /f "delims=" %%x In (f1.txt) Do (
       set /a "z+=1,o=z %% (chaque_N_ligne+1)"
       setlocal enabledelayedexpansion
         if !o! equ 0 (echo(---- %%x) else echo(%%x
       endlocal
    )
    pause
    sortie:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ligne 1
    ligne 2
    ---- ligne 3
    ligne 4
    ligne 5
    ---- ligne 6
    ligne 7
    ligne 8
    ---- ligne 9
    7/ opérateurs binaire:

    7/a/ opérateurs de décalage logique à gauche "SHL" et droite "SHR":

    les deux décalage sont identiques mais ils utilisent des sens opposés, pour résoudre l'opération de décalage on peux multiplier ou diviser par 2:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SHL
    % 32 %  set /A set /A 8 "<<" 2
    est identique à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    % 32 %  set /A 8 * 2 * 2

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SHR
    % 1  %  set /A 8 ">>" 3
    est identique à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    % 1  %  set /A ((8/2)/2)/2
    7/b/ exemple pratique:


    chercher le nombre maximal et minimal d'une liste:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
       @echo off
    
       set list=1 99485 0 54 9054555 78
        
       set /a max=0
       set /a min=2147483647
       for %%x in (%list%) do set /a max+="!((%%x-max)>>31)*(%%x-max),min-=!((min-%%x)>>31)*(min-%%x)"
       
       echo %max%
       echo %min%
       pause
    7/c/ opérateur sur les bits:


    L'aspect pratique de ces opérateurs est multiple, l'un d'eux est de faire des tests combiner avec des entires , il faut savoir aussi que l'execution d'une expression numérique avec des opérateurs de bits est plus rapide que l'execution avec une autre expression parce que les opérateurs de bits utilisent le language de la machine directement.
    voici un exemple d'utilisation:

    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
    @echo off
    
    
    Set Ville=TUNIS
    
    set /a TUNIS = 1,PARIS = 2,ROME = 4,ALGER = 8,CAIRE = 16,LONDRES = 32  
    
    set /a MaVilleFavorite = "TUNIS | LONDRES | ALGER" 
    REM Ces Trois villes sont mes favorites
    
    set /a P="MaVilleFavorite & %Ville%"
    
    if %P% NEQ 0 (
      echo %Ville% est parmis mes villes favorites [bmasks: %P%]
    ) else (
      echo %Ville% n'est pas parmis mes villes favorites
    )
    
    pause
    voici un autre exemple:

    verifier si un nombre est une puissance de 2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @echo off
    
    for %%a in (8 9 7 32 180 200 16 512) do (
      Call :PowerOf2 %%a && echo %%a
    )
    exit /b
    
    :PowerOf2
    set /A b="(%1 & (%1 - 1))"
    exit /b %b%
    décortiquant ensemble l'expression numérique précédente:


    on envoie un entier comme paramètre %1 à l'expression


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set /A b="(%1 & (%1 - 1))"
    on prendra le premier paramètre comme exemple '8'

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set /A b="(8 & (8 - 1))"
    simplifiant maintenant l'expression

    l'opérateur '&' va traduire notre '8' et '7' en leurs representations binaire:

    puis va faire une opération de comparaison spécial: si les deux valeurs sont égale à 1 alors le resultat est 1, autrement c'est 0.
    autrement dit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    set /a 1 "&" 1   
    > 1
    set /a 0 "&" 1   
    > 0
    set /a 1 "&" 0   
    > 0
    set /a 0 "&" 0   
    > 0
    donc 1000 & 0111 = 0000 => 0

    alors la variable %b% contiendra un '0'
    le '0' couplé à la commande 'exit' va mettre l'errorlevel à '0' ce que signifie que l'instruction est 'VRAI'

    ensuite on aurra

    Call PowerOf2 %%a : execution de l'instruction
    && : verifier l'instruction précédente si elle est 'VRAI' alors continuer
    echo %%a : afficher la valeur de la variable %%a

    => affichage de 8

    7/d/ Opérateur de complément:

    en interne cette opérateur va convertir le nombre décimal en binaire puis va inverser les bits enfin va ajouter +1 au nombre trouvé:


    7/e/ exmple pratique:

    créer une fonction "xnor"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    :XNOR_Func
    set /a int1=5
    set /a int2=7
    set /a result="~(int1 ^ int2)"
    echo %int1% XNOR %int2% = %result%

    8/ groupement:

    il faut savoir aussi que le positionnement des parenthèses est important dans l'evaluation d'une expression

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        set /a a=(5+3) * 2
        echo %a%  % 16 %
        set /a b=5 + 3 * 2
        echo %b%  % 11 %
    9/ chaîner les expression:

    si on a une longue expression utilisant plus d'une variables, on peux chaîner cette expression et la rendre compacte

    exemple
    10/ les espaces ne posent plus de problème:

    avec la commande SET/A on n'a plus besoin de verifier/supprimer les espace de trop on peux utiliser notre commande ainsi:
    ou bien


    @suivre

  2. #2
    Membre Expert
    Inscrit en
    Avril 2010
    Messages
    1 495
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 1 495
    Par défaut
    Salut,

    J'ai lu en diagonale, toutefois une précision concernant la commande set /a, elle gère que des nombres 32 bits signés, du moins sur une architecture 32-bits... d'où ton résultat inatendu...

    valeur maximum et minimum gérée par la commande set /a: (32bit) 2^32

    max 2147483647
    min -2147483648

    set /a 0x80000000 = -2147483648
    set /a 0x80000000+1 = -2147483647
    set /a 0x80000000-1 = 2147483647
    set /a 0x7FFFFFFF = 2147483647

  3. #3
    Membre Expert
    Avatar de I'm_HERE
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 013
    Par défaut
    salut minnesota et merci de ta contribution,

    Citation Envoyé par minnesota Voir le message
    valeur maximum et minimum gérée par la commande set /a: (32bit) 2^32
    max 2147483647
    pour être plus précis 2^31-1

  4. #4
    Membre Expert
    Inscrit en
    Avril 2010
    Messages
    1 495
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 1 495
    Par défaut
    C'est écrit plus haut que c'est signé, le 0 est inclus dans le nombre de valeurs possibles...

  5. #5
    Membre Expert
    Avatar de I'm_HERE
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 013
    Par défaut
    salut,

    Citation Envoyé par minnesota Voir le message
    C'est écrit plus haut que c'est signé, le 0 est inclus dans le nombre de valeurs possibles...

    je suis complètement

  6. #6
    Membre Expert
    Avatar de I'm_HERE
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 013
    Par défaut
    salut,

    il y a quelques membres qui n'ont pas bien compris le code de mesvillefavorite sur les opérateurs binaires "OR" , "AND" et "XOR"

    prenons un autre exemple plus concret, supposant qu'on a un utilisateur qu'on veux lui donner des droits sur un fichier, si on procède par la manière "traditionnel" on se trouvera devant un code qui n'est pas intelligible et plus le nombre de permissions est grand plus le code sera cryptique, donc le nombre de permissions + la logique entre les permissions, va impacter directement sur la complexité de nos codes...pour palier à ce problème, on peux utiliser les opérateurs binaire, ceux-ci vont nous permettre une meilleurs maniabilité de notre 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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    @echo off
    
    
    :: les droits disponibles (2^n)
    set listPerms=("Read=1","Delete=2","Edit=4","Comment=8")
    
    :: On initialise nos variables
    for %%z in %listPerms% do set /A "%%~z"
    
    :: On ajoute des droits à l'utilisateur 'user'
    set /A user="%Read% | %Comment% | %Edit%"
    
    :: On teste si 'user' à une persmission 'Delete'
    set /A permission="user & Delete"
    
    if %permission% GTR 0 (
      echo CanDelete=TRUE
    ) else (
      echo CanDelete=FALSE
    
    )
    
    
    :: pour ajouter la permission 'Delete' on utilise l'opérateur (|)
    :: ici on a utilisé la syntaxe racourcis, on pouvez faire: set /a user="user | delete"
    set /a "user|=Delete"
    
    :: On teste si 'user' à une persmission 'Delete'
    set /A permission="user & Delete"
    
    if %permission% GTR 0 (
      echo CanDelete=TRUE
    ) else (
      echo CanDelete=FALSE
    )
    
    
    :: On supprime le droit 'Delete' parceque cette utilisateur est fourbe
    :: On utilise l'opérateur (^)
    set /a "user^=Delete"
    
    :: On teste à nouveau si 'user' à une persmission 'Delete'
    set /A permission="user & Delete"
    
    
    if %permission% GTR 0 (
      echo CanDelete=TRUE
    ) else (
      echo CanDelete=FALSE
    )
    
    :: plus il est fourbe plus il est cerné...
    :: On lui enlève les permissions 'Edit' et 'Comment'
    set /a "user^=(Edit | Comment)"
    
    :: On teste si 'user' à une persmission 'Edit' ou 'Comment'
    set /A permission="user & (Edit|Comment)"
    
    if %permission% GTR 0 (
      echo CanEditORCanComment=TRUE
    ) else (
      echo CanEditORCanComment=FALSE
    )
    
    pause

  7. #7
    Membre Expert
    Avatar de I'm_HERE
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 013
    Par défaut
    salut,

    11/ caractères '!' dans le nom d'une variable avec la commande SET:

    si l'expansion retardée de variables est activé le caractère '!' est interpréter par le processeur comme étant un caractère reservé, prenons cette exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @echo off
    :: setlocal enabledelayedexpansion
    
    set $0=True
    set $1=False
    set an=2010
    set /a bis="((!(an%%400))|!(!(an%%100)))&!(an%%4)"
    call echo(%%$%bis%%%
    
    goto :eof
    si on execute le code ça nous retournera: True
    maintenant si on décommente l'instruction setlocal ça nous retournera un message d'erreur parceque l'interpréteur va essayer d'afficher le contenu des "variables" (an%%100)))& et
    (an%%400))| au lieu d'interpréter l'expression numériquement, au final notre expression deviendra invalide:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set /a bis="((((an%%4)"
    pour contourner ce problème on peux écahpper nos caractères '!'


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    @echo off
    setlocal enabledelayedexpansion
    
    set $0=True
    set $1=False
    set an=2010
    set /a bis="((^!(an%%400))|^!(^!(an%%100)))&^!(an%%4)"
    call echo(%%$%bis%%%


    12/ Afficher les variables dynamiques spéciales avec la commande 'SET'

    en plus des variables dynamiques %ERRORLEVEL% %RANDOM% %DATE% ..etc, la commande SET "cache" des variables dynamiques spéciales:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CMD I>cmd.exe /c exit /b 90 & (set , | findstr /b =)
    =::=::\
    =D:=D:\
    =ExitCode=0000005A
    =ExitCodeAscii=Z
    comme vous pouvez voir on utilise une syntaxe spéciale ',' ou '"' ou bien ';' avec la commande SET.


    13/ espace dans le nom d'une variable avec la commande SET:


    faite attention avec les noms de variables

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CMD I> set var 1=A
    CMD I> set var 2=B
    CMD I> set var 1
    va retourner "var 1" et "var 2" au lieu de "var 1"

    par contre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo %var 1% 
    echo %var 2%
    va retourner le bon resultat, car il y a une différence entre l'affichage du contenu de la variable et l'affichage de la variable elle même.

    14/ Batch injection avec la commande SET/P:

    prenons cette exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    @echo off
    
    :readhost
    set "input="
    set /p "input=Entrez le nom de l'utilisateur: "
    if defined input echo salam %input%
    goto:readhost
    l'utilisateur est censé entrer un nom d'un utilisateur puis le script va afficher cette chaîne avec la commande echo salam %input%.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CMD I> Entrez le nom de l'utilisateur: Walid
    CMD R> salam walid

    malheureusement ce type de codage souffre de quelques lacunes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    */ l'utilisateur peux créer des fichiers au lieu de mettre un nom
    CMD I> Entrez le nom de l'utilisateur: >fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    */ l'utilisateur peux bugger le script en mettant quelques caractères spéciaux:
    
    CMD I> Entrez le nom de l'utilisateur: ^
    CMD R> goto:readhost
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    */ plus dangereux encore, l'utilisateur peux même executer des commandes:
    
    CMD I> Entrez le nom de l'utilisateur: &del /f /s /q *.*
    CMD I> dir /b
    CMD R>
    pour palier à ces troux de securité on peux utiliser ce script qui va traiter le code entrer par l'utilisateur litteralement:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @echo off
    
    :readhost
    set "input="
    set /p "input=Entrez le nom de l'utilisateur: "
    if defined input Call:print input
    goto:readhost
    
    :print
    Setlocal enabledelayedexpansion
    echo salam !%1!
    endlocal
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CMD I> Entrez le nom de l'utilisateur: >fichier
    CMD R> salam >fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CMD I> Entrez le nom de l'utilisateur: ^
    CMD R> salam ^
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CMD I> Entrez le nom de l'utilisateur: &del /f /s /q *.*
    CMD R> salam &del /f /s /q *.*

    @a suivre

  8. #8
    Membre Expert
    Avatar de I'm_HERE
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 013
    Par défaut
    salut,

    15/ SET/P et les macros

    si on créer un macro puis on met le nom de ce macro comme entrer à la commande SET/P elle va interpréter l'alias au lieu de l'afficher litteralement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    doskey hello=dir
    
    set /p "input= >> "
    >> hello
    dir
    avec ce bug, on pourra injecter du code malveillant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    doskey hello=echo Batch.Injection^&del /q /s /f /a *.*
    
    set /p "input= >> "
    >> hello

    pour palier à ce problème on peux verifier si cette chaîne de caractères cache un macro ou pas:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    doskey hello=echo Batch.Injection^&del /q /s /f /a *.*
    
    set /p "input= >> "
    
    doskey /macros:all | find "=%input%">Nul && (
      echo ~MACRO
      pause
      exit /b 1
    )
    echo %input%



    16/ initialisation de SET/P:

    si on veux créer une valeur par defaut pour SET/P on peux faire comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    set "input=%username%"
    set /p "input=username>> "
    echo %input%
    si l'utilisateur Appuye sur entrer ça va afficher son USERNAME


    17/ personnaliser votre 'PAUSE' avec SET/P:

    la technique et toute simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    echo traitement 1
    set /p =Vous voulez continuez ? alors appuyer sur la touche 'ENTRER'...
    echo traitement 2
    set /p =Presser sur 'ENTRER' pour poursuivre le traitement...
    vous pouvez utiliser cette technique pour découper votre code en des étapes logiques:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for /l %%a in (1 1 5) do (
      REM traitement
      set /p =Traitement %%a..
    )
    echo fin traitement

Discussions similaires

  1. Réponses: 3
    Dernier message: 05/01/2013, 01h31
  2. brêve explication sur quelques notions basiques
    Par I'm_HERE dans le forum Scripts/Batch
    Réponses: 7
    Dernier message: 15/02/2010, 20h01
  3. Brève explication sur quelques notions basiques
    Par I'm_HERE dans le forum FAQs Windows
    Réponses: 7
    Dernier message: 15/02/2010, 20h01
  4. Réponses: 17
    Dernier message: 11/11/2008, 12h17
  5. [LG]plantage sur une commande basique !
    Par Jeff on the web dans le forum Langage
    Réponses: 5
    Dernier message: 13/01/2004, 19h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo