Älä käytä globaaleja muuttujia, ellei kirjaimellisesti ole muuta vaihtoehtoa, piste. Se on ihan ok tällaisiin pikkuasioihin, mutta mielestäni on tärkeää selvittää miten asiat tehdään oikein jo varhaisessa vaiheessa.
Siinä, globaalit muuttujat ovat yleisesti ottaen aika kamalia… ellet käytä niitä vain referenssinä etkä koskaan muuta niitä funktiosta käsin. Miksi sillä on väliä? Koska jos sinulla on kymmenen funktiota, jotka kaikki käyttävät samaa muuttujaa, jotka vaikkapa muuttavat tekemisiään tuon muuttujan perusteella, ja mikä tahansa niistä voi mahdollisesti muuttaa sitä, yhtäkkiä niiden kaikkien käyttäytyminen muuttuu äärimmäisen arvaamattomaksi.
Mitä sinun pitää sen sijaan oppia tuntemaan, on funktion ulostulon kaappaaminen. Tuotat dataa, objekteja, tekstiä, mitä ikinä haluat, ja sitten tallennat tuon tuotoksen johonkin, kun kutsut funktiota. Kun funktio on valmis, tuo säiliö pitää sisällään tarvitsemasi arvon.
Tätä on paljon helpompi seurata, koska päädyt tällaisiin riveihin:
$variable = Function-Name -Parameter1 'ParameterValue'
Tiedät yhdellä silmäyksellä, että tämä muuttuja sisältää kyseisen funktion tulosteen, ja voit vain katsoa funktiosta, mitä saat. Vertaa globaaleihin muuttujiin:
$global:Var = 'initial value'Function-Name -Parameter1 'ParameterValue'# check the value of $global:Var$global:Var
Eikä sinulla ole aavistustakaan siitä, pitääkö tämä muuttuja edelleen sisällään alkuperäisen arvon. Tämä vaikutus pahenee, kun alat käyttää voimakkaasti globaaleja muuttujia, ja sinulla on suuria vaikeuksia seurata, mitä oma koodisi tekee.
Mitä siis teet, jotta asiat pysyvät järkevinä?
Esimerkissäsi funktiosta:
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
Kerrotaanpa vielä:
- Funktiot ensin. Määrittele funktiot ennen kuin teet mitään muuta. Funktioita voidaan käyttää missä tahansa koodissa, joten on paljon hyödyllisempää, jos sinulla on johdonmukainen paikka, josta voit tarkistaa funktiot. On vain yksinkertaisempaa pitää ne alussa, jolloin et joudu etsimään koko komentosarjasta, mihin laitoit sen funktion, jota haluat muuttaa.
- Määrittele parametrit. Kaikki tiedot, joita funktiosi tarvitsee käyttää laajemmasta skriptistä, tulisi määritellä sen parametreissa. Näin näet yhdellä silmäyksellä, mitä dataa funktio tarvitsee, ja voit myös olla varma, että annat funktiolle oikeaa dataa, etkä ole vahingossa mongertanut sitä jonnekin muualle skriptissäsi.
- Output!
Write-Output
on hyvin selkeä tapa tehdä se, mutta oletusarvoisesti pelkkä datan ’putoaminen’ ulostulovirtaan antamalla sen ’pudota’ sieppaamatta sitä (esim. antamalla sen seistä rivillä itsekseen) aiheuttaa sen tulostumisen. Suosin selkeämpää syntaksia, jossa määritetään, että ”kyllä, annan tämän datan ulos”. - Kapteeni! Tekeminen
$var = function-name
tarkoittaa periaatteessa ”kutsun tätä funktiota ja kaappaan minkä tahansa tulosteen muuttujaan$var
”. Näin voit käyttää tätä dataa myöhemmin, ja koska määrittelet sen samassa paikassa kuin käytät sitä, on paljon helpompi seurata, mitä olet tekemässä koodillasi. - Objektityypit. Käytät PSObject-tyyppiä ja rakennat sen käyttämällä hashtablea. Se, mitä minä teen, on hyvin samanlaista, mutta yleensä PsCustomObject on joustavampi tyyppi kaikkeen, mitä tarvitset. Se muotoutuu helpommin ja toimii saumattomammin kaikkien cmdlettien kanssa.
-
Lisätietoa: nuo hakasulkeet ovat niin sanottuja ”attribuutteja”. Ne ovat ylimääräisiä bittejä, joita voit soveltaa funktioihin eri käyttötarkoituksilla.
ilmoittaa, että tämä on ”edistynyt funktio” (minusta typerä nimi, mutta he valitsivat sen nimen). Periaatteessa tämän avulla voit hyödyntää oletusparametreja, joita PS sallii funktioilla olla. Voit tehdä asioita, kuten kutsua
Write-Verbose
jättämään tietoa siitä, mitä olet tekemässä, joka on normaalisti piilossa (koska sitä ei yleensä tarvita), mutta sitten kutsua funktiota-Verbose
-parametrilla nähdäksesi viestit (jos jokin ei mene niin kuin odotat, jotta näet, missä se menee pieleen).-attribuutteja voidaan määritellä kullekin parametrille tällä tavoin. Voit määritellä tietyt sijainnit, sen, ovatko ne pakollisia, ja monia muita asioita, kuten sen, hyväksyvätkö ne putkiston syötteen.
Tässä mielessä tässä on siis, miten itse käsittelisin tätä funktiota:
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
Enemmän tai vähemmän vain lyhensin sitä, tein joitain hienompia juttuja ja tein siitä putkiston kanssa toimivan, jotta voit tehdä saman asian vähemmillä vaiheilla. Myönnän, että olen luultavasti täysin ylivoimainen tässä, joten älä pelkää tökkiä sitä pala palalta ja kysyä kysymyksiä kaikesta, mistä et ole varma. Tässä on asioita, joita en maininnut edellä, mutta hei! Voit joko käyttää runsaasti Get-Help
tai Googlea, ja minä olen tukenasi kaikessa, mihin tarvitset ”pähkinänkuoressa” olevan selityksen tai mitä tahansa, mitä sinun on vaikea ymmärtää.
Onnea matkaan, se voi olla vähän villiä. 😀