N’utilisez pas de variables globales à moins qu’il n’y ait littéralement aucune autre option, période. C’est bien pour de petites choses comme ça, mais je pense qu’il est important de comprendre comment faire les choses correctement dès le début.
Donc, les globales sont assez terribles en général… à moins que vous ne les utilisiez que comme référence et que vous ne les modifiez jamais à partir d’une fonction. Pourquoi cela est-il important ? Parce que si vous avez dix fonctions qui utilisent toutes la même variable et qui, disons, changent ce qu’elles font en fonction de cette variable, et que n’importe laquelle d’entre elles pourrait éventuellement la changer, soudainement le comportement de toutes ces fonctions devient extrêmement imprévisible.
Ce avec quoi vous devez plutôt vous familiariser, c’est la capture de la sortie d’une fonction. Vous sortez des données, des objets, du texte, tout ce que vous voulez, et ensuite vous stockez cette sortie dans quelque chose lors de l’appel de la fonction. Une fois la fonction terminée, ce conteneur contient la valeur dont vous avez besoin.
C’est beaucoup plus facile à suivre, car vous vous retrouvez avec des lignes comme celle-ci:
$variable = Function-Name -Parameter1 'ParameterValue'
Vous savez d’un coup d’œil que cette variable contient la sortie de cette fonction, et vous pouvez simplement regarder la fonction pour voir ce que vous obtenez. Comparez aux variables globales:
$global:Var = 'initial value'Function-Name -Parameter1 'ParameterValue'# check the value of $global:Var$global:Var
Et vous n’avez aucune idée si cette variable contient toujours la valeur originale. Cet effet est aggravé lorsque vous commencez à utiliser fortement les variables globales, et vous aurez beaucoup de difficultés à suivre ce que fait votre propre code.
Alors, que faites-vous pour que les choses restent raisonnables ?
Dans l’exemple de votre fonction :
function Get-DiskSize { param( $Drives ) $Drives | ForEach-Object { $Vol = ("$_" + ":") $WMIPriorDisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='$Vol'" | Select-Object Size, FreeSpace $PriorDiskObject = @{ DriveLetter = $Vol DiskSizePrior = "{0:N2}" -f ($WMIPriorDisk.Size / 1GB) DiskFreePrior = "{0:N2}" -f ($WMIPriorDisk.FreeSpace / 1GB) } Write-Output $PriorDiskObject } }$Drives = (::GetDrives() | Where-Object {$_.DriveType -eq "Fixed"} | Select-Object -ExpandProperty 'Name').Replace(":\","")$DisksPrior = Get-DiskSize -Drives $Drives
Laissez-moi le décomposer :
- Les fonctions d’abord. Définissez vos fonctions avant de faire quoi que ce soit d’autre. Les fonctions peuvent être utilisées n’importe où dans le code, donc c’est beaucoup plus utile si vous avez un endroit cohérent pour vérifier vos fonctions. Il est juste plus simple de les garder au début, ainsi vous ne cherchez pas dans tout le script où vous avez mis cette fonction que vous devez modifier.
- Définir les paramètres. Toute donnée que votre fonction doit utiliser à partir du script plus large doit être définie dans ses paramètres. Cela vous permet de voir d’un coup d’œil quelles sont les données dont une fonction a besoin, et cela vous permet également d’être sûr que vous allez lui donner les bonnes données, et que vous ne les avez pas accidentellement mélangées ailleurs dans votre script.
- Sortie !
Write-Output
est une façon très claire de le faire, mais par défaut, le simple fait de laisser les données « tomber » sur le flux de sortie en ne les capturant pas (par exemple, en les laissant se tenir sur une ligne par elles-mêmes) provoquera leur sortie. Je préfère la syntaxe plus claire consistant à spécifier que « oui, je sors ces données ». - Capturer ! Faire
$var = function-name
signifie essentiellement « appeler cette fonction et capturer toute sortie dans la variable$var
« . Cela vous permet d’utiliser ces données plus tard, et parce que vous les définissez au même endroit que vous les utilisez, il est beaucoup plus facile de suivre ce que vous faites avec votre code. - Types d’objets. Vous utilisez le type PSObject, et vous le construisez en utilisant une table de hachage. Ce que je fais est très similaire, mais vous trouverez généralement que PsCustomObject est un type plus flexible pour tout ce que vous avez besoin de faire. Il se formate plus facilement et fonctionne de manière plus transparente avec tous les cmdlets.
-
Bidbits supplémentaires : ces crochets sont ce qu’on appelle des « attributs ». Ce sont des bits supplémentaires que vous pouvez appliquer à vos fonctions avec des utilisations diverses.
déclare qu’il s’agit d’une « fonction avancée » (nom stupide pour moi, mais c’est ce qu’ils ont choisi de l’appeler). Fondamentalement, cela vous permet d’utiliser les paramètres par défaut que PS permet aux fonctions d’avoir. Vous pouvez faire des choses comme appeler
Write-Verbose
pour laisser derrière vous des informations sur ce que vous faites qui sont normalement cachées (parce qu’elles ne sont généralement pas nécessaires), mais ensuite appeler la fonction avec le paramètre-Verbose
pour voir les messages (si quelque chose ne se passe pas comme vous l’attendez, afin que vous puissiez voir où ça foire).attributs peuvent être définis pour chaque paramètre comme ça. Vous pouvez définir des positions spécifiques, s’ils sont obligatoires, et beaucoup d’autres choses, comme s’ils acceptent l’entrée du pipeline.
Donc, avec cela en tête, voici comment je traiterais moi-même cette fonction :
function Get-DiskSize { param( ] $Drives ) process { $Drives | ForEach-Object { $Vol = ("$_" + ":") Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='$Vol'" | Select-Object -Property @{ Name = 'TotalSpace' Expression = { "{0:N2}" -f ($_.Size / 1GB) } }, @{ Name = 'FreeSpace' Expression = { "{0:N2}" -f ($_.FreeSpace / 1GB) } } } } }$DisksPrior = (::GetDrives() | Where-Object {$_.DriveType -eq "Fixed"} | Select-Object -ExpandProperty 'Name').Replace(":\", "") | Get-DiskSize
Je l’ai plus ou moins juste raccourcie, j’ai fait quelques choses plus fantaisistes, et je l’ai fait fonctionner avec le pipeline pour que vous puissiez faire la même chose en moins d’étapes. Je reconnais que je vous submerge probablement complètement ici, alors s’il vous plaît n’ayez pas peur de poke at it piece by piece et de poser des questions sur tout ce dont vous n’êtes pas sûr. Il y a des choses que je n’ai pas mentionnées ci-dessus, mais bon ! Vous pouvez soit faire un usage abondant de Get-Help
ou de Google, et je suis juste là pour tout ce dont vous avez besoin d’une explication « en résumé », ou tout ce que vous avez du mal à comprendre.
Bonne chance là-bas, ça peut devenir un peu sauvage 😀
.