Question Joindre les membres issus de deux commandes

Plus d'informations
il y a 17 ans 8 mois #2541 par Legabs

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... ;) apparement tu n'initialises jamais la variable $stats non ? alors j'ai juste apporté une modification :

[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 :p le dictionnaire est vide à la fin. Et comme je ne connais pas la syntaxe exacte de ce genre de formules... notamment à quoi servent les ?{} et les %{}, j'ai un peu de mal à le déboguer. Mais peut-être sauras-tu trouver d'où vient le problème avec mes explications ?

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.

Plus d'informations
il y a 17 ans 8 mois #2543 par Laurent Dardenne
Legabs écrit:

Je ne sais pas si c'est dans le manuel, mais ça a l'air de fonctionner.

Belle astuce, je ne connaissait pas ce comportement :
[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:

apparement tu n'initialises jamais la variable

Exact, un oubli :-/
Legabs écrit:

Et d'ailleurs ça ne marche toujours pas

Oui dans ce cas il faut réémettre l'objet $stat dans le pipe ce que fait \"|Get-Mailboxstatistics\" :
[code:1]$dict = @{};Get-mailbox -Server myServer| ? {$_.UserPrincipalName} | %{$stats = Get-Mailboxstatistics -Identity $_.UserPrincipalName; $stats}|%{$dict.($_.UserPrincipalName) = $stats}[/code:1]
A tester donc ;)
Legabs écrit:

à quoi servent les ?{} et les %{},

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.
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.

Plus d'informations
il y a 17 ans 8 mois #2545 par Legabs

Belle astuce, je ne connaissait pas ce comportement

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é B)

A tester donc


:( Ça ne fonctionne toujours pas. Maintenant il me renvoie l'erreur suivante :

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.( &lt;&lt;&lt;&lt; $_.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.

Plus d'informations
il y a 17 ans 8 mois #2547 par Laurent Dardenne
Legabs écrit:

Je pense que c'est ? = Foreach et % = Where, non ?

Oui. Décidément :blink:

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.

Plus d'informations
il y a 17 ans 8 mois #2548 par Legabs

Je croise les doigts...


:laugh: Hé bah en tout cas $dict est bel et bien rempli maintenant. Ceci étant, il contient plus d'entrées que le script sur plusieurs lignes. Je m'explique :

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(\&quot;MailboxStatistics\&quot;«»), 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 :)<br><br>Message édité par: Legabs, à: 3/07/08 16:03

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

Plus d'informations
il y a 17 ans 8 mois #2549 par Laurent Dardenne
Legabs écrit:

Ceci étant, il contient plus d'entrées que le script sur plusieurs lignes.

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.
Legabs écrit:

Je pense néanmoins qu'il vaut mieux écrire quelque chose de souple face aux incohérences ;)

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.
Legabs écrit:

En plus pour l'instant utiliser un script sur une ligne ne semble pas apporter d'amélioration de performances significative

Oui je m'en doutais un peu mais on ne pouvait le savoir qu'en vérifiant.
Pour info un script n'est pas identique à un pipeline car le script apporte une notion de portée.
Legabs écrit:

il faut que j'ajoute des données

Dans ce cas crée un PSObject via Select, enfin c'est une autre solution comme d'utiliser une tableau à 2 dimensions:
[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:

Parce que l'imbrication de deux hashtables ça m'oblige à faire des casts à rallonge dans mon code VB.NET.

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 ?
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.

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