Question
Joindre les membres issus de deux commandes
- Legabs
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
- Messages : 17
- Remerciements reçus 0
C'est une affectation ou un test ( -eq ) ?
C'est les deux en fait. J'affecte ma variable $stats et si jamais l'affectation échoue (aucun contenu) je ne fais pas ce qu'il y a dans les accolades.
Je ne sais pas si c'est dans le manuel, mais ça a l'air de fonctionner.
En ce qui concerne ton code, il ne marchait pas...
[code:1]$dict = @{};Get-mailbox -Server myServer| ? {$_.UserPrincipalName} | %{$stats = Get-Mailboxstatistics -Identity $_.UserPrincipalName)}|%{$dict.($_.UserPrincipalName) = $stats}[/code:1]
J'ai rajouté le %{$stats =. Et d'ailleurs ça ne marche toujours pas
Il faudrait vérifier si Get-Mailboxstatistics peut ne renvoyer que les informations nécessaires.
Je ne sais pas, mais de toute façon ça n'est pas bien grave puisque je suis susceptible de manipuler une majorité des informations renvoyées par Get-MailboxStatistics.
Le script s'exécute sur le serveur ?
Pas directement sur le serveur Exchange non. Mais sur une machine qui héberge un WebService. Je crois qu'au pire la boucle foreach sera pas mal du tout.
Ensuite il faut vérifier les temps de réponse lors de montée en charge
Pour ça, il faudra que j'agrandisse ma base de test... ce qui sera assez long à faire. Mais je pense que si on demande au serveur Exchange de préparer toutes les données et de les renvoyer d'un seul bloc, la montée en charge devrait se passer raisonnablement bien. Il vaut toujours mieux ça que de faire la boucle sur le WebService et d'interroger le serveur Exchange par de multiples requêtes.
ps
je ne vois pas de gestion d'erreur dans ton code VB.
Je l'ai supprimée pour poster mais rassure-toi, le mécanisme existe bel et bien
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Belle astuce, je ne connaissait pas ce comportement :Je ne sais pas si c'est dans le manuel, mais ça a l'air de fonctionner.
[code:1]
# sous CTP2 v2
PS >if ($stat=$null) {\"ok\"} else {\"nok\"}
# if ($null) {\"ok\"} else {\"nok\"}
ok
PS >$?
true
PS >if ($stat=10) {\"ok\"} else {\"nok\"}
# if (10) {\"ok\"} else {\"nok\"}
ok
PS >$?
true
[/code:1]
$? indique si la dernière opération a réussi, je pense que le test se base sur la présence de la valeur $null l'opérateur not fonctionne aussi ( !$null) et le résulat suit...
Legabs écrit:
Exact, un oubli :-/apparement tu n'initialises jamais la variable
Legabs écrit:
Oui dans ce cas il faut réémettre l'objet $stat dans le pipe ce que fait \"|Get-Mailboxstatistics\" :Et d'ailleurs ça ne marche toujours pas
[code:1]$dict = @{};Get-mailbox -Server myServer| ? {$_.UserPrincipalName} | %{$stats = Get-Mailboxstatistics -Identity $_.UserPrincipalName; $stats}|%{$dict.($_.UserPrincipalName) = $stats}[/code:1]
A tester donc
Legabs écrit:
Il s'agit de raccouris pour les cmdlet Where-objet Where (?) et Foreach-Object ou Foreach (?). Where et foreach étant des alias de nom de cmdlet.à quoi servent les ?{} et les %{},
J'aurais dû utilser les alias qui sont plus explicite.<br><br>Message édité par: Laurent Dardenne, à: 3/07/08 13:14
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Legabs
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
- Messages : 17
- Remerciements reçus 0
Ben en fait c'est quelque chose qui fonctionne avec beaucoup de langages de programmation avec lesquels je suis un peu plus à l'aise. Alors j'ai essayé et c'est passéBelle astuce, je ne connaissait pas ce comportement
A tester donc
Key ne peut pas être null.
Nom du paramètre : key
Au niveau de ligne : 1 Caractère : 153
+ $dict = @{};Get-mailbox -Server myServer | ? {$_.UserPrincipalName} | %{$stats = Get-Mailboxstatistics -Identity $_.UserPrincipalName; $stats}|%{$dict.( <<<< $_.UserPrincipalName) = $stats}
... et le dictionnaire est, forcément, toujours vide. Mais ça m'intrigue parce que Key c'est $_.UserPrincipalName, et il n'y a pas de raison qu'il soit null celui là !
Il s'agit de raccouris pour les cmdlet Where-objet Where (?) et Foreach-Object ou Foreach (?).
Je pense que c'est ? = Foreach et % = Where, non ?
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Oui. DécidémentJe pense que c'est ? = Foreach et % = Where, non ?
Et pour le code même confusion, il faut renvoyer $_ et pas la variable $stat qui elle reste accessible dans les segments de pipeline suivants :
[code:1]
$dict = @{};Get-mailbox -Server myServer|? {$_.UserPrincipalName} | %{$stats = Get-Mailboxstatistics -Identity $_.UserPrincipalName; $_}| %{$dict.($_.UserPrincipalName) = $stats}
[/code:1]
Je croise les doigts...
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Legabs
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
- Messages : 17
- Remerciements reçus 0
Je croise les doigts...
Je ne sais pas pourquoi mais le script sur plusieurs lignes élimine les entrée pour lesquelles il n'a pas été possible de récupérer de statistiques. En revanche ton script sur une ligne crée une entrée pour chaque UserPrincipalName trouvé.
Bon tu vas me dire que c'est pas normal qu'une boîte mail puisse ne pas avoir de statistiques associées. C'est vrai mais je travaille sur une base de test et il peut apparaître quelques incohérences. Je pense néanmoins qu'il vaut mieux écrire quelque chose de souple face aux incohérences
En plus pour l'instant utiliser un script sur une ligne ne semble pas apporter d'amélioration de performances significative (on reste dans les 5~6 secondes pour 65 boîtes mail).
En plus je viens de me rendre compte qu'il faut que j'ajoute des données dans ce que je retourne. Donc je pense que je vais passer au code suivant :
[code:1]$mbs = Get-mailbox -Server myServer
$dict = @{}
$data = @{}
foreach ($mb in $mbs) {
if ($mb.UserPrincipalName) {
if ($stats = Get-Mailboxstatistics -Identity $mb.UserPrincipalName) {
# Si la boîte mail utilise les paramètres par défaut du MailboxStore
if ($mb.UseDatabaseQuotaDefaults -eq $true) {
# On récupère les données propres à la MailboxDatabase
$mbdb = Get-MailboxDatabase -Identity $mb.Database
$data.ProhibitSendQuota = $mbdb.ProhibitSendQuota
$data.ProhibitSendReceiveQuota = $mbdb.ProhibitSendReceiveQuota
$data.IssueWarningQuota = $mbdb.IssueWarningQuota
} else { # Sinon
# On récupère les données propres à la boîte mail
$data.ProhibitSendQuota = $mb.ProhibitSendQuota
$data.ProhibitSendReceiveQuota = $mb.ProhibitSendReceiveQuota
$data.IssueWarningQuota = $mb.IssueWarningQuota
}
$data.MailboxStatistics = $stats
$dict.($mb.UserPrincipalName) = $data
}
}
}
return $dict
[/code:1]
Par contre ça redevient un peu crade non ? Parce que l'imbrication de deux hashtables ça m'oblige à faire des casts à rallonge dans mon code VB.NET.
[code:1]Dim ht As Hashtable = CType(resultsStats.Item(0).BaseObject, Hashtable)
For Each dictEntry As DictionaryEntry In ht
WriteConsole(dictEntry.Key)
Dim data As Hashtable = CType(CType(dictEntry.Value, PSObject).BaseObject, Hashtable)
Dim mbs As MailboxStatistics = CType(CType(data(\"MailboxStatistics\"«»), PSObject).BaseObject, MailboxStatistics)[/code:1]
M'enfin bon, quoiqu'il en soit, je crois qu'on se rapproche pas mal du but, et vraiment merci
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Je vois que je ne suis pas encore au point pour la transformation de script en segments de pipeline, j'ai tenu compte du premier test mais pas du second.Ceci étant, il contient plus d'entrées que le script sur plusieurs lignes.
Legabs écrit:
Je suis de ton avis, si on sait qu'il y a des incohérences et qu'on les remonte, ça c'est une approche professionnelle.Je pense néanmoins qu'il vaut mieux écrire quelque chose de souple face aux incohérences
Legabs écrit:
Oui je m'en doutais un peu mais on ne pouvait le savoir qu'en vérifiant.En plus pour l'instant utiliser un script sur une ligne ne semble pas apporter d'amélioration de performances significative
Pour info un script n'est pas identique à un pipeline car le script apporte une notion de portée.
Legabs écrit:
Dans ce cas crée un PSObject via Select, enfin c'est une autre solution comme d'utiliser une tableau à 2 dimensions:il faut que j'ajoute des données
[code:1]$mbs = Get-mailbox -Server myServer
$dict = @{}
$data = Select ProhibitSendQuota,ProhibitSendReceiveQuota,IssueWarningQuota -input $mbdb
foreach ($mb in $mbs) {
if ($mb.UserPrincipalName) {
if ($stats = Get-Mailboxstatistics -Identity $mb.UserPrincipalName) {
# Si la boîte mail utilise les paramètres par défaut du MailboxStore
if ($mb.UseDatabaseQuotaDefaults -eq $true) {
# On récupère les données propres à la MailboxDatabase
$mbdb = Get-MailboxDatabase -Identity $mb.Database
$data = Select ProhibitSendQuota,ProhibitSendReceiveQuota,IssueWarningQuota -input $mbdb
} else { # Sinon
# On récupère les données propres à la boîte mail
$data = Select ProhibitSendQuota,ProhibitSendReceiveQuota,IssueWarningQuota -input $mb
}
add-member -input $Data -name MailboxStatistics -value $stats
$dict.($mb.UserPrincipalName) = $data
}
}
}
return $dict
[/code:1]
Attention j'ai écrit sans vérifier la syntaxe mais le principe est là.
Legabs écrit:
Là je dois dire que je suis un peu limité pour t'aider, je n'y connais rien en VB.NET mais DirectCast ne serais pas plus approprié/rapide ?Parce que l'imbrication de deux hashtables ça m'oblige à faire des casts à rallonge dans mon code VB.NET.
Ensuite regarde si la manipulation d'une classe spécifique (compilé) peut simplifier ton code, ie. manipuler une instance créé dans VB et pas dans PS. Inverser le pb en qq sorte ...
Enfin bref cela demande un peu plus de temps, il a surement plus simple mais pour l'instant je ne sais pas faire.
Mais par curiosité je vais étudier le pb.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Entraide pour les débutants
- Joindre les membres issus de deux commandes