Question Stocker résultat dans une variable

Plus d'informations
il y a 15 ans 6 mois #7803 par Debbia
Bonjour tout le monde,

Je découvre le Powershell en ce moment et je suis confronté à un problème qui me rend fou :)

J'ai un script tout simple qui doit récupérer les lettres des partitions et les scanner pour récuperer les fichier faisant plus de 500Mo:
[code:1]$test = Get-WmiObject Win32_LogicalDisk | select-object DeviceID

function GrosFichiers
{

foreach ($part in $test)

{Get-ChildItem $part -recurse | Sort-Object length -descending | where-object { $_.length -gt 500000000 } | ft directory,name,length -wrap –auto}
}

GrosFichiers $test
[/code:1]

Le problème c'est que quand je le lance il me retourne ceci :

Lecteur introuvable. Il n'existe aucun lecteur nommé « @{DeviceID=Z ».
à : ligne:10 caractère:16
+ {Get-ChildItem <<<< $part -recurse | Sort-Object length -descending | where-object { $_.length -gt 500000000 } | ft directory,name,length -wrap –auto}


En gros il ne récupère pas la lettre comme je le désire mais un résultat comme cela: @{DeviceID=C 

Comment faire pour qu'il m'interprète cela convenablement?

Merci d'avance pour votre aide.

Cordialement.

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

Plus d'informations
il y a 15 ans 6 mois #7804 par Richard Lazaro
Bonjour,

Alors c'est tout bête, ta commande WMI retourne un tableau d'objet (si yen a plusieurs) de type Selected.System.Management.ManagementObject

Et tu as dedans une propriété (enfin une NoteProperty).
[code:1]
[PS] > $test | Get-Member


TypeName: Selected.System.Management.ManagementObject

Name MemberType Definition
----

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

Quand tu fais ton foreach, ta variable $part récupère un objet de ta liste d'objet.

Le problème, c'est que ce n'est pas une chaîne de caractère (string) alors que le paramètre Path de la cmdlet Get-ChildItem attend un string.

Ton objet est alors transformé en string mais pas correctement ...

Il existe deux solution, soit tu t'amuses à redéfinir la méthode ToString() de l'objet ... long et embêtant pour ce que tu as à faire.

Soit tu appels la NoteProperty de l'objet contenu dasn ta variable $path, cad :

$test = Get-WmiObject Win32_LogicalDisk | select-object DeviceID

[code:1]
$test = Get-WmiObject Win32_LogicalDisk | select-object DeviceID

function GrosFichiers
{
foreach ($part in $test)
{
Get-ChildItem $part.DeviceID -recurse | Sort-Object length -descending | where-object { $_.length -gt 500000000 } | ft directory,name,length -wrap –auto
}
}

GrosFichiers $test
[/code:1]

Voilà, normalement cela devrait fonctionner ;]

Bien Cordialement,
Richard Lazaro.

Think-MS : (Get-Life).Days | %{ Learn-More }

\\"Problems cannot be solved by the same level of thinking that created them.\\" - Albert Einstein

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

Plus d'informations
il y a 15 ans 6 mois #7805 par Debbia
C'est tout a fait ça!

Je viens de trouver et je dois dire que c'est tout bête mais quand on ne sait pas c'est pas évident.

Merci pour le temps passé à m'aider :)

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

Plus d'informations
il y a 15 ans 6 mois #7806 par Richard Lazaro
C'était pas grand chose, juste le temps de rédiger une explication claire pour pas donner un script brut ;p

Think-MS : (Get-Life).Days | %{ Learn-More }

\\"Problems cannot be solved by the same level of thinking that created them.\\" - Albert Einstein

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

Plus d'informations
il y a 15 ans 6 mois #7808 par Laurent Dardenne
Richard Lazaro écrit:

Ton objet est alors transformé en string mais pas correctement ...

Richard je suis tout à fait d'accord avec ton explication, mais ici, je sais je suis pointilleux, la conversion en string est correcte, c'est le résultat qui est inadapté à l'usage.
De redéfinir la méthode ToString() permet justement de l'adapter (spécialiser) à cet usage.
Comme Select-object construit un objet de type PSObject, la méthode ToString de ce type renvoi une chaîne dans un format 'spécialisé'.
Richard Lazaro écrit:

Le problème, c'est que ce n'est pas une chaîne de caractère (string) alors que le paramètre Path de la cmdlet Get-ChildItem attend un string.

Une autre approche est d'inverser le pb en déclarant sur l'objet un alias ou en choisissant un nom de membre reconnu afin de s'appuyer les mécanismes du pipeline, ici on part donc du nom du paramètre attendu, Path, et pas du type de l'objet :
[code:1]
#Get-ChildItem gére, via le pipeline, les membres Path et LiteralPath
#Le membre Path existe déjà sur une instance WMI
$test = Get-WmiObject Win32_LogicalDisk | select-object @{N=\"LiteralPath\";E={$_.DeviceID}}
$test[1]|Get-ChildItem

$test = Get-WmiObject Win32_LogicalDisk | Add-member -membertype aliasproperty -name LiteralPath -value DeviceID -secondvalue System.String -pass
$test[1]|Get-ChildItem
[/code:1]
Ensuite en allant plus loin on peut réécrire le code :
[code:1]
function Get-Files {
param (
#pas de position
#si on n'utilise pas le pipe on doit préciser son nom -InputObject ou -I
#le paramètre suivant sera considéré comme étant en position 0, car innommé
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
$InputObject,
[Parameter(Position=0)]
[Int64]
$size=500000000,
[switch] $Recurse,
[switch] $ForceRoot)

Process
{
if (Test-Path $_.Path)
{
if ($ForceRoot)
{cd \"$($_.Path)\\"}
$_|Get-ChildItem -recurse:$recurse |
where-object { $_.length -gt $size }
}
#else { write-Warning $_.Path}
}#process
}

Get-WmiObject Win32_LogicalDisk |
Select-Object @{N=\"Path\";E={$_.DeviceID}}|
Get-Files -size 1000 -recurse|
Sort-Object length -descending |
ft directory,name,length -wrap –auto
[/code:1]
N4rk0o, afin d'accélérer le traitement l'appel à Sort-Object doit être placé dans les derniers segments du pipeline.
La fonction Get-Files respecte la convention de nommage préconisée par MS et elle renvoie une liste de fichiers, la présentation est un autre traitement qui doit se faire au cas par cas et en dehors de la fonction.
Autre chose, l'accés aux lecteurs se fait dans le répertoire courant, il peut donc ne pas être à la racine, soit tu déclares un switch pour traiter le cas soit tu précises le comportement dans la doc.
On déclare $Recurse pour le propager ou non lors de l'appel à Get-ChildItem, etc, etc.

Cela nécessite de passer un peu plus de temps à coder, l'avantage est qu'en procédant de cette manière à terme tu gagneras du temps.
Ici l'appel à $part.DeviceID est le plus pratique, mais l'objet traité dans la fonction est lié à un appel préalable à Win32_LogicalDisk, un autre avantage d'utiliser les mécanismes du pipeline est qu'ils permettent de varier la source des objets.

C'est vrai que lorsqu'on débute tout ça n'est pas évident à saisir et peut même embrouiller.
Une fois que l'on compris ces qq principes de base on n'utilise plus PowerShell de la même manière.

Tutoriels PowerShell

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

Plus d'informations
il y a 15 ans 6 mois #7809 par Debbia
Merci pour vos réponses et votre aide!

J'ai bien pris note de tes remarques :)

Cordialement.

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

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