Question Souci avec boucle Foreach

Plus d'informations
il y a 8 ans 5 mois #20786 par Marco_FR
Souci avec boucle Foreach a été créé par Marco_FR
Bonjour,

J'ai un petit souci avec un script.
L'objectif de mon script est de récupérer le prénom et nom dans un fichier csv.
Puis d'ajouter ces personnes dans un groupe.

Voici le script de base que j'avais fais:


[code:1]###### Ajouter une liste de personnes dans un groupe AD

Function GetAdGroup ($group) {
$users = @(Get-ADGroupMember \"$group\" | select -ExpandProperty SamAccountName)
#$users
if ($users.count -gt 0) {
foreach ($users in $users) {
Get-ADUser -Identity $users -Properties DisplayName | select DisplayName, GivenName, Surname, SamAccountName | sort DisplayName
}
}
}

#$CSV = Read-Host -Prompt \"Saisir le chemin du fichier csv\"
#$USER = @(Import-Csv -Delimiter \";\" \"$CSV\"«»)
$USER = @(Import-Csv -Delimiter \";\" \"add_users_group.csv\"«»)
$USERLIST = $USER.Name

$CUSERLIST = $USERLIST.count
$GROUP = \"GPG_TEST\"
$GGROUP = @(Get-ADGroupMember $GROUP)

if ( $CUSERLIST -gt 1 )
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNES\";
}
else
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNE\";
}

foreach ($USERLIST in $USERLIST )
{
# Donne le SamAccountName du compte qui va être ajouté
$USERPRENOM = $USER.Prenom
$USERNOM = $USER.Nom
$GUSER = @(Get-ADUser -Filter {(surname -eq $USERPRENOM) -and (givenname -eq $USERNOM)} -Properties displayname)
$GUSERSAM = @($GUSER.SamAccountName)
$GUSERDISPLAY = @($GUSER.DisplayName)
Write-Host -BackgroundColor Black -ForegroundColor Green \"la personne se nomme : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow \"$USERLIST\"

# Donne le DisplayName du compte qui est ajouté au groupe souhaité
Add-ADGroupMember -Identity $GROUP -Members $GUSERSAM
Write-Host -BackgroundColor Black -ForegroundColor Green \"le compte \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow \"$GUSERSAM\" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Green \" a été ajouté au groupe : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $GROUP
}
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le groupe : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $GGROUP.count \"PERSONNE(S)\"
if ( $CUSERLIST -gt 1 )
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNES\";
}
else
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNE\";
}
Write-Host \"Il y a ces personnes dans le groupe :\"
GetAdGroup $GROUP | sort SamAccountName[/code:1]

Le souci de ce script c'est que si j'ai plusieurs personnes, il remplace les variables $USERPRENOM et $USERNOM par les différents prénoms et noms.
Mais si j'ai une personne ça fonctionne :P


Ensuite, j'ai trouvé une option intéressante de Foreach, l'option -Process, avec ce paramètre sur mes variable j'ai bien un seul prénom et un seul nom mais j'ai un message d'erreur que je comprends pas.

[code:1]###### Ajouter une liste de personnes dans un groupe AD
<# Dans le fichier .csv il faudra inverser le contenu du champ DisplayName pour que le nom soit correcte#>


Function GetAdGroup ($group) {
$users = @(Get-ADGroupMember \"$group\" | select -ExpandProperty SamAccountName)
#$users
if ($users.count -gt 0) {
foreach ($users in $users) {
Get-ADUser -Identity $users -Properties DisplayName | select DisplayName, GivenName, Surname, SamAccountName | sort DisplayName
}
}
}

#$CSV = Read-Host -Prompt \"Saisir le chemin du fichier csv\"
#$USER = @(Import-Csv -Delimiter \";\" \"$CSV\"«»)
$USER = @(Import-Csv -Delimiter \";\" \"add_users_group.csv\"«»)
$USERLIST = $USER.Name

$CUSERLIST = $USERLIST.count
$GROUP = \"GPG_TEST\"
$GGROUP = @(Get-ADGroupMember $GROUP)

if ( $CUSERLIST -gt 1 )
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNES\";
}
else
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNE\";
}

$USER | ForEach-Object -Process {
# Donne le SamAccountName du compte qui va être ajouté
$GUSER = @(Get-ADUser -Filter {(surname -eq $_.Prenom) -and (givenname -eq $_.Nom)} -Properties displayname)
$GUSERSAM = @($GUSER.SamAccountName)
$GUSERDISPLAY = @($GUSER.DisplayName)
Write-Host -BackgroundColor Black -ForegroundColor Green \"la personne se nomme : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow \"$USERLIST\"

# Donne le DisplayName du compte qui est ajouté au groupe souhaité
Add-ADGroupMember -Identity $GROUP -Members $GUSERSAM
Write-Host -BackgroundColor Black -ForegroundColor Green \"le compte \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow \"$GUSERSAM\" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Green \" a été ajouté au groupe : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $GROUP
}
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le groupe : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $GGROUP.count \"PERSONNE(S)\"
if ( $CUSERLIST -gt 1 )
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNES\";
}
else
{
Write-Host -BackgroundColor Black -ForegroundColor Green \"Il y a dans le fichier importé : \" -NoNewline;
Write-Host -BackgroundColor Black -ForegroundColor Yellow $CUSERLIST \"PERSONNE\";
}
Write-Host \"Il y a ces personnes dans le groupe :\"
GetAdGroup $GROUP | sort SamAccountName[/code:1]

le message d'erreur est : [code:1]Get-ADUser : Propriété : « Prenom » introuvable dans l’objet du type : « System.Management.Automation.PSCustomObject[/code:1]

Je vérifie les type de membres de mon objet $USER

[code:1]TypeName : System.Management.Automation.PSCustomObject

Name MemberType Definition
----

Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Name NoteProperty System.String Name=TEST Marco
Nom NoteProperty System.String Nom=Test
Prenom NoteProperty System.String Prenom=Marco
[/code:1]
Et là je suis un peu perdu. En espérant ne pas vous avoir perdu aussi :silly:

Par avance, merci de votre aide et de votre temps.<br><br>Message édité par: Marco_Po, à: 2/10/15 10:20

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 ans 5 mois #20788 par Matthew BETTON
Réponse de Matthew BETTON sur le sujet Re:Souci avec boucle Foreach
Bonjour,

Utilises les balises 'Code' et ton message sera nettement plus lisible ;)

Matthew

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 ans 5 mois #20790 par Marco_FR
Réponse de Marco_FR sur le sujet Re:Souci avec boucle Foreach
Voilà

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 ans 5 mois #20791 par Matthew BETTON
Réponse de Matthew BETTON sur le sujet Re:Souci avec boucle Foreach
Marco_Po écrit:

Voilà


C'est effectivement beaucoup plus mieux ;)

Je n'ai pas encore tout lu que je vois déjà un problème dans l'écriture de ta boucle foreach

[code:1]foreach ($USERLIST in $USERLIST )[/code:1]

Un truc comme (à revoir peut être pour le nom de la variable)

[code:1]foreach ($USER in $USERLIST )[/code:1]

me paraît être mieux...

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 ans 5 mois #20793 par Matthew BETTON
Réponse de Matthew BETTON sur le sujet Re:Souci avec boucle Foreach
Marco_Po écrit:


le message d'erreur est : [code:1]Get-ADUser : Propriété : « Prenom » introuvable dans l’objet du type : « System.Management.Automation.PSCustomObject[/code:1]

Je vérifie les type de membres de mon objet $USER

[code:1]TypeName : System.Management.Automation.PSCustomObject

Name MemberType Definition
----



Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Name NoteProperty System.String Name=TEST Marco
Nom NoteProperty System.String Nom=Test
Prenom NoteProperty System.String Prenom=Marco
[/code:1]
Et là je suis un peu perdu. En espérant ne pas vous avoir perdu aussi :silly:


A partir du moment où tu utilises un pipe et redirige l'objet de type 'ADUser' vers des Cmdlets telles que 'Select-Object' ou 'Sort-Object', l'objet est \&quot;cassé\&quot;. On perd le type sur l'objet d'origine pour créer un type personnalisé.

[code:1]Get-ADUser toto | Get-Member
TypeName : Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition
----

Contains Method bool Contains(string propertyName)
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator()
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string p...
DistinguishedName Property System.String DistinguishedName {get;set;}
Enabled Property System.Boolean Enabled {get;set;}
GivenName Property System.String GivenName {get;set;}
Name Property System.String Name {get;}
ObjectClass Property System.String ObjectClass {get;set;}
ObjectGUID Property System.Nullable`1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, ...
SamAccountName Property System.String SamAccountName {get;set;}
SID Property System.Security.Principal.SecurityIdentifier SID {get;set;}
Surname Property System.String Surname {get;set;}
UserPrincipalName Property System.String UserPrincipalName {get;set;}

[/code:1]

Le type d'objet est conservé : \&quot;Microsoft.ActiveDirectory.Management.ADUser\&quot;

[code:1]Get-ADUser toto | select -name | Get-Member

TypeName : Selected.Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition
----

Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
name NoteProperty System.String name=toto
[/code:1]

Le type d'objet est maintenant : \&quot;Selected.Microsoft.ActiveDirectory.Management.ADUser
\&quot;

A toi de réserver le 'select-object' et/ou le 'sort-object' en sortie du script, ou même laisses à l'utilisateur de ton script utiliser ou non le select et le sort, en fonction de son besoin.

Évites de coder avec des pipes et ces Cmdlets dans tes fonctions.

Conserve / préserve le type d'origine ... Penses à 'mon code, mes fonctions, mon script peuvent être ré utilisés par quelqu'un d'autre'.

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 ans 5 mois #20794 par Marco_FR
Réponse de Marco_FR sur le sujet Re:Souci avec boucle Foreach
Merci Mattew, j'ai changé avec le code que tu proposais

[code:1]foreach ($USERS in $USERLIST )[/code:1]

Voici le contenu de mon fichier csv

[code:1]Name;Prenom;Nom
TEST Marc;Marc;Test
Le Mojito;Marco;Mojito[/code:1]

En mode débug dans ISE:

[code:1]$USERPRENOM = @($USER.Prenom)
$USERNOM = @($USER.Nom)
$GUSER = @(Get-ADUser -Filter {(surname -eq $USERPRENOM) -and (givenname -eq $USERNOM)} -Properties displayname)[/code:1]

[code:1]$USER.Prenom = Marc Marco[/code:1]

Lorsqu'il fait la recherche, il ne trouve pas mon utilisateur.

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.080 secondes
Propulsé par Kunena