[..] Fonction récursive

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
lokidor
Niveau 3
Niveau 3
Messages : 36
Enregistré le : mar. 08 févr. 2011 10:57
Localisation : Sophia Antipolis
Status : Hors ligne

[..] Fonction récursive

#1

Message par lokidor »

Bonjour,

Je viens à vous car j'ai mis au point un script qui est sensé être récursif mais qui veux pas ><

Sur le principe : j'ai un utilisateur qui appartient a différents groupes. Ces groupes contenant eux même d'autres groupes et ainsi de suite.

Mon idée, c'est : je prends le user, je tire la liste de ces groupe, je prends le premier groupe j'écris dans un fichier qui il est et qui est son parent, je regarde ces groupes, je prends le premier, j'écris etc... et ainsi de suite jusqu'à un groupe qui n'en contient pas d'autres. Et à ce moment là, on remonte un étage au dessus et on refait la même chose avec le second groupe. De cette manière on remonte petit à petit en faisant tous les groupes.

Mon soucis, c'est qu'arrivé au fond de la première branche, ben pas moyen de remonter :(
Je pense que ça vient du fait qu'il ne peut récupérer le nom du groupe au dessus.

J'ai fait de la récursivité en cours, mais j'ai toujours eu du mal ><

Je pense bien qu'il me manque un moyen de de revenir en arrière quand je suis au bout, mais je ne parvient pas à m'en sortir :/

Merci aux âmes charitables qui sauront me sortir de ce bourbier :)

le code :

Code : Tout sélectionner

Global $MOF_grp
Global $MOF_CSV = "***/***/***/RecursiveMemberOf_résultat.txt"
Global $MOF_handler_CSV

;petite fonction prise de _ADfunction.au3 et modifié pour faire bien les choses
;fonction qui va chercher la liste des memberOf d'un user AD et le retourne dans un tableau $memberof
Func ADGetUserGroups(ByRef $memberof, $user = @UserName)

    Local $objItem

    $strHostServer = $objRootDSE.Get("dnsHostName") ; Retrieve the name of the connected DC

    $objItem = ObjGet("LDAP://" & $strHostServer & "/" & $user) ; Retrieve the COM Object for the logged on user

    $memberof = $objItem.GetEx("memberof")

;~     MsgBox(64,"debug","memberof : "&$memberof)
;~     _ArrayDisplay($memberof)

    $count = UBound($memberof)

    _ArrayInsert($memberof, 0, $count)

EndFunc   ;==>_ADGetUserGroups

Func RecursiveListGroup($MOF_userDN)
    ADGetUserGroups($MOF_grp,$MOF_userDN)
;~     _ArrayDisplay($MOF_grp)

    If IsArray($MOF_grp) Then
        For $MOF_cpt=1 To $MOF_grp[0]

;~             MsgBox(64,"Fini", $MOF_grp[0])
;~             _ArrayDisplay($MOF_grp)

            ;on écrit le résultat dans le CSV
            FileWrite($MOF_handler_CSV,"Père : "&_ADDNToSamAccountName($MOF_userDN)&" ----> Fils : "&_ADDNToSamAccountName($MOF_grp[$MOF_cpt])&@CRLF)
            FileWrite($MOF_handler_CSV,"--------------------------------"&@CRLF)

            ;on rappelle la fonction pour aller plus bas
            RecursiveListGroup($MOF_grp[$MOF_cpt])
        Next
    Else

        ;on écrit dans le CSV qu'il n'y a pas de fils pour ce groupe
        FileWrite($MOF_handler_CSV,"Pas de descendance pour : "&_ADDNToSamAccountName($MOF_userDN)&"!"&@CRLF)
        FileWrite($MOF_handler_CSV,"--------------------------------"&@CRLF)

    EndIf

EndFunc

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg

        Case $MOF_GO

            ;ouverture du fichier
            $MOF_handler_CSV=FileOpen($MOF_CSV,1)

            ;on lit l'entrée de l'utilisateur (à savoir quel user AD on doit aller regarder)
            $MOF_user = GUICtrlRead($MOF_user_input)

            ;on écrit l'en tête du fichier
            FileWrite($MOF_handler_CSV,"--------"&_NowDate() &" "& _NowTime() &" -------- Fiche des groupes de  : "&$MOF_user&" --------"&@CRLF)

            ;on met le nom donné sous la bonne forme pour AD
            $MOF_user_DN  = _ADSamAccountNameToFQDN($MOF_user)

            ;appel de la fonction récursive
            RecursiveListGroup($MOF_user_DN)

            ;fermeture du fichier
            FileClose($MOF_handler_CSV)

            ;Fin du programme
            MsgBox(64,"Fini", "Traitement terminé")

    EndSwitch
WEnd
Edit : simplification du code
Loki,

Le monde avance grâce aux paresseux!
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11824
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Fonction récursive

#2

Message par Tlem »

Je ne doute pas que vos explications sont extrêmement claires pour vous. Malheureusement, après 3 lectures j'avoue avoir un peut de mal à entrevoir la portée globale de votre question. Cela est sans doute le fait que nous soyons Vendredi soir et que je suis quelque peu fatigué.
Mis à par ses quelques considérations et afin de facilité la compréhension de la problématique, quelques images ou dessins pour neuneu m'aiderai grandement à comprendre votre histoire d'utilisateur et de groupe et ce que vous souhaitez obtenir.

Pour résumer, qu'avez-vous comme données et que voulez-vous obtenir en résultat.
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Fonction récursive

#3

Message par sylvanie »

Bonsoir,
Ce qui n'est pas facile est de faire tourner le script, car il est très "environement" dépendant.
Cependant, je pense qu'il y a déjà au moins un soucis sur $MOF_grp :
Cette variable est globale, or par récursivité, elle se fait écraser par les appels à ADGetUserGroups. Comme elle est déclarée comme globale, alors en sortie de la premère brache exploirée, on ne tombe plus sur le tableau initial.

Pour la faire plus clair, déclarez là en "local" dans la fonction RecursiveListGroup, ainsi le contenu de la variable ne sera pas écrasée par l'appel à ADGetUserGroups dans les autres itérations.

Tenez nous au courant ;)
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
Avatar du membre
sksbir
Niveau 7
Niveau 7
Messages : 384
Enregistré le : lun. 26 oct. 2009 17:57
Localisation : Lyon
Status : Hors ligne

Re: [..] Fonction récursive

#4

Message par sksbir »

Bonjour

Je dirais pour ma part qu'il y a un problème d'architecture.
Alors on a
;fonction qui va chercher la liste des memberOf d'un user AD et le retourne dans un tableau $memberof
Func ADGetUserGroups(ByRef $memberof, $user = @UserName)
et
Func RecursiveListGroup($MOF_userDN)

Ce qui ne va pas, c'est qu'on trouve un appel à ADGetUserGroups dans la fonction RecursiveListGroup.

Dans le principe, pour chaque utilisateur, on cherche donc la liste des groupes directs ( fonction ADGetUserGroups ) , et pour chaque groupe direct rencontré , on devrait appeler la fonction RecursiveListGroup pour trouver la liste des groupes indirects.

Donc, ADGetUserGroups appelle RecursiveListGroup , et RecursiveListGroup s'appelle lui même , mais en aucun cas RecursiveListGroup ne doit appeler ADGetUserGroups .

Et puis pour ce qui est de stocker tout ça dans un tableau, je te conseille de déclarer ton tableau en global, d'utiliser tableau[0] comme compteur d'éléments déja remplis, et de ne pas passer tableau[] en paramètre de tes fonctions.


Et puis dans le principe de la récursivité, il ne faut pas se casser la tête sur la façon de "remonter". En fait, "remonter", c'est juste que le script "fils" se termine et permet à son "père" de continuer son traitement...
lokidor
Niveau 3
Niveau 3
Messages : 36
Enregistré le : mar. 08 févr. 2011 10:57
Localisation : Sophia Antipolis
Status : Hors ligne

Re: [..] Fonction récursive

#5

Message par lokidor »

Merci à tous pour vos réponses :)

En effet, déclarer mon tableau en global était une erreur, parmi tant d'autres :p

J'ai repris tout ça au calme chez moi durant ma période de cours avec une de mes profs de prog.

Je me rends compte en vous écrivant que j'ai oublié le fichier en question chez moi -_-

Je ramène ça demain. Je pense en tout cas que je ne suis plus très loin de la solution, vous me direz ce que vous en pensez ;) (promis je ferais un gros effort pour la compréhension, bien que l'on ne soit plus vendredi :P )

Encore merci à tous et à demain
Loki,

Le monde avance grâce aux paresseux!
Avatar du membre
sksbir
Niveau 7
Niveau 7
Messages : 384
Enregistré le : lun. 26 oct. 2009 17:57
Localisation : Lyon
Status : Hors ligne

Re: [..] Fonction récursive

#6

Message par sksbir »

Créer le tableau globalement n'est pas une erreur en soi : c'est pas parce qu'un script est récursif qu'il ne doit pas alimenter un seul et même tableau pour tout l'empilement d'invocation.

Maintenant, si tu réinitialise le tableau au niveau global à chaque invocation, là, ça va plus marcher...
lokidor
Niveau 3
Niveau 3
Messages : 36
Enregistré le : mar. 08 févr. 2011 10:57
Localisation : Sophia Antipolis
Status : Hors ligne

Re: [..] Fonction récursive

#7

Message par lokidor »

Voili voilou, j'ai modifié la fonction récursive, je vous reposte pas ce qui vas autour, ça ne devrait pas avoir changé (en dehors du tableau de résultat qui n'est plus en global)

Code : Tout sélectionner

Func RecursiveListGroup($MOF_userDN)
    ;on récupère la liste des groupes dans $MOF_userDN
    ADGetUserGroups($MOF_grp,$MOF_userDN)

    If IsArray($MOF_grp) Then
            For $MOF_cpt=1 To $MOF_grp[0]

                ;on écrit le résultat dans le CSV
                FileWrite($MOF_handler_CSV,"Père : "&_ADDNToSamAccountName($MOF_userDN)&" ----> Fils : "&_ADDNToSamAccountName($MOF_grp[$MOF_cpt])&@CRLF)
                FileWrite($MOF_handler_CSV,"--------------------------------"&@CRLF)

                ;on rappelle la fonction pour aller plus bas
                RecursiveListGroup($MOF_grp[$MOF_cpt])
            Next
    Else
        ;on écrit dans le CSV qu'il n'y a pas de fils pour ce groupe
        FileWrite($MOF_handler_CSV,"Pas de descendance pour : "&_ADDNToSamAccountName($MOF_userDN)&"!"&@CRLF)
        FileWrite($MOF_handler_CSV,"--------------------------------"&@CRLF)
    EndIf

EndFunc

 

Je penses que mon problème se situe à ce niveau là :

Code : Tout sélectionner

If IsArray($MOF_grp) Then
 
Car lorsque je n'ai qu'un enregistrement dans le tableau, il passe le test de IsArray, mais desuite après il me sort une erreur et se stop :
test_MemberOfRecursif.au3 (61) : ==> Subscript used with non-Array variable.:
FileWrite($MOF_handler_CSV,"Père : "&_ADDNToSamAccountName($MOF_userDN)&" ----> Fils : "&_ADDNToSamAccountName($MOF_grp[$MOF_cpt])&@CRLF)
FileWrite($MOF_handler_CSV,"Père : "&_ADDNToSamAccountName($MOF_userDN)&" ----> Fils : "&_ADDNToSamAccountName($MOF_grp^ ERROR
Merci pour votre aide :)

Edit : J'ai oublié de faire un "dessin" pour une meilleur compréhension du problème :P

Donc en fait, je prends un User ActiveDirectory et j'extraie ces groupes.
Ensuite, pour chaque groupe extrait, je regarde s'il n'y a pas d'autres groupes a l'intérieur de ces groupes précédemment extraits.
Je souhaite répéter ce schéma jusqu'à ce que j'arrive tout au fond de l'arborescence.

J'espère avoir été clair. Si ce n'est pas le cas, n'hésitez pas à me le dire :)
Loki,

Le monde avance grâce aux paresseux!
Avatar du membre
sksbir
Niveau 7
Niveau 7
Messages : 384
Enregistré le : lun. 26 oct. 2009 17:57
Localisation : Lyon
Status : Hors ligne

Re: [..] Fonction récursive

#8

Message par sksbir »

je vois que tu ne tiens pas compte de mes remarques... dommage, d'autant plus que dans ta dernière réponse tu décris correctement le processus quand tu le décris en clair, mais tu ne l'applique pas à ton propre script.
lokidor
Niveau 3
Niveau 3
Messages : 36
Enregistré le : mar. 08 févr. 2011 10:57
Localisation : Sophia Antipolis
Status : Hors ligne

Re: [..] Fonction récursive

#9

Message par lokidor »

sksbir a écrit : Ce qui ne va pas, c'est qu'on trouve un appel à ADGetUserGroups dans la fonction RecursiveListGroup.

Donc, ADGetUserGroups appelle RecursiveListGroup , et RecursiveListGroup s'appelle lui même , mais en aucun cas RecursiveListGroup ne doit appeler ADGetUserGroups .
Là, je ne vois pas pourquoi. Dans me tête, ce serait plutôt l'inverse, RecursivListGroup a besoin de savoir quels sont les groupes, il faut donc bien qu'il appelle ADGetUserGroups non? En tout cas je n'ai pas bien compris ton conseil là dessus ^^'
sksbir a écrit : Et puis pour ce qui est de stocker tout ça dans un tableau, je te conseille de déclarer ton tableau en global, d'utiliser tableau[0] comme compteur d'éléments déja remplis, et de ne pas passer tableau[] en paramètre de tes fonctions.
Je veux bien, mais je ne vois pas comment gérer l'index du tableau :( il faudrait le passer en paramètre?

Et surtout on risque de se retrouver avec un array d'une taille un peu exagérée je pense car la quantité de groupes est assez importante(30 à 40 groupes au premier niveau).
sksbir a écrit :je vois que tu ne tiens pas compte de mes remarques... dommage
J'ajouterais juste que je n'ai pas pas tenu compte de tes conseil, le code que j'ai posté aujourd'hui a été écrit il y a quelques semaines, et je n'était pas revenu dessus avant de poster ce matin. N'y vois aucune marque d'irrespect :oops:
sksbir a écrit :d'autant plus que dans ta dernière réponse tu décris correctement le processus quand tu le décris en clair, mais tu ne l'applique pas à ton propre script.

haa... :roll:
Il me semblait pourtant avoir suivi la même logique.




Merci encore
Loki,

Le monde avance grâce aux paresseux!
Avatar du membre
sksbir
Niveau 7
Niveau 7
Messages : 384
Enregistré le : lun. 26 oct. 2009 17:57
Localisation : Lyon
Status : Hors ligne

Re: [..] Fonction récursive

#10

Message par sksbir »

lokidor a écrit :
sksbir a écrit : Ce qui ne va pas, c'est qu'on trouve un appel à ADGetUserGroups dans la fonction RecursiveListGroup.
Donc, ADGetUserGroups appelle RecursiveListGroup , et RecursiveListGroup s'appelle lui même , mais en aucun cas RecursiveListGroup ne doit appeler ADGetUserGroups .
Là, je ne vois pas pourquoi. Dans me tête, ce serait plutôt l'inverse, RecursivListGroup a besoin de savoir quels sont les groupes, il faut donc bien qu'il appelle ADGetUserGroups non? En tout cas je n'ai pas bien compris ton conseil là dessus ^^'
Ben non. Tu l'appelles avec un seul argument obligatoire : le nom du groupe dont tu veux scanner la liste des groupes secondaires ( enfin, le chemin AD complet du nom du groupe, c'est plus facile).
Donc, la logique du script est celle-ci:
- pour chaque groupe de l'utilisateur, j'appelle RecursivListGroup (nomgroupe)
- Dans RecursivListGroup, je fais la liste des groupes du groupe passé en argument. Pour chaque groupe trouvé, j'appelle RecursivListGroup.

Tu vois donc bien que RecursivListGroup n'a besoin que d'un truc en entrée : le nom du groupe à explorer. Il n'a pas non plus besoin de faire appel ADGetUserGroups. Pourquoi faire?? il a tout ce qu'il faut...
sksbir a écrit : Et puis pour ce qui est de stocker tout ça dans un tableau, je te conseille de déclarer ton tableau en global, d'utiliser tableau[0] comme compteur d'éléments déja remplis, et de ne pas passer tableau[] en paramètre de tes fonctions.
Je veux bien, mais je ne vois pas comment gérer l'index du tableau :( il faudrait le passer en paramètre?
Et surtout on risque de se retrouver avec un array d'une taille un peu exagérée je pense car la quantité de groupes est assez importante(30 à 40 groupes au premier niveau).
J'ai mis un tableau de 500, et je n'ai jamais explosé. L'index du tableau, c'est la case 0. tableau[0]=3 : tu as déjà renseigné 3 groupes ( dans tableau[1], tableau[2], et tableau[3] ).

ps : si j'avais considéré ça comme de l'irrespect, je n'aurais tout simplement plus rien posté ici ;)
pps : je te laisse réfléchir encore un peu, et après je te donne la solution qui est opérationnelle chez moi.
lokidor
Niveau 3
Niveau 3
Messages : 36
Enregistré le : mar. 08 févr. 2011 10:57
Localisation : Sophia Antipolis
Status : Hors ligne

Re: [..] Fonction récursive

#11

Message par lokidor »

yep merci beaucoup en tout cas.

Pour le moment je suis passé sur un autre outils a développer, mais je reviens sur celui ci dans le courant de la semaine prochaine.

Je ne perds pas espoir :D
Loki,

Le monde avance grâce aux paresseux!
Répondre