Articles

Foreach and Where magic methods

ForEach og Hvor er to ofte brukte konsepter som har vært tilgjengelig I PowerShell siden versjon 1 kom ut i 2006. ForEach har vært tilgjengelig som både en uttalelse og en cmdlet( ForEach-Object), slik at du kan iterere gjennom en samling objekter og ta litt handling en gang for hvert objekt i den samlingen. Where har vært tilgjengelig som en cmdlet (Where-Object), slik at du kan filtrere ut elementer i en samling som ikke passerer noen betingelse, en betingelse som kan evalueres ved hjelp av egenskapene på objekter i samlingen eller objektene selv som tilhører samlingen. ForEach-evnen til å iverksette tiltak på elementer i en samling og Where-evnen til å filtrere en samling er funksjoner som er svært nyttige og er inkludert i en eller annen form i logikken bak Mange PowerShell-skript, kommandoer og moduler, uansett hvilken Versjon Av PowerShell som brukes. Faktisk er De så mye brukt at de har vært et fokusområde for forbedring av ytelse, funksjonalitet og syntaks I PowerShell-versjoner 3.0 og 4.0.

med utgivelsen Av Windows PowerShell 4.0 ble to nye «magiske» metoder introdusert for samlingstyper som gir en ny syntaks for tilgang Til ForEach og Hvor evner I Windows PowerShell. Disse metodene er treffende kalt ForEach Og Hvor. Jeg kaller disse metodene «magiske» fordi de er ganske magiske i hvordan De fungerer I PowerShell. De vises ikke I Get-Member-utgang, Selv Om du bruker-Force Og request-MemberType Alle. Hvis du ruller opp ermene og graver inn med refleksjon, kan du finne dem; det krever imidlertid et bredt søk fordi de er private utvidelsesmetoder implementert på en privat klasse. Men selv om de ikke kan oppdages uten å kikke under dekslene, er de der når du trenger dem, de er raskere enn sine eldre kolleger, og de inkluderer funksjonalitet som ikke var tilgjengelig i sine eldre kolleger, derav den «magiske» følelsen de forlater deg med når du bruker Dem I PowerShell. Dessverre forblir disse metodene udokumenterte selv i dag, nesten et år siden de ble offentliggjort, så mange innser ikke kraften som er tilgjengelig i disse metodene. Denne artikkelen vil prøve å rette opp det ved å forklare hvor de kan brukes og hvordan de fungerer slik at du kan utnytte denne magien når Du bruker PowerShell.

et notat Om PowerShell 3.0

Før jeg kommer inn på å forklare hvordan ForEach og Hvor metoder fungerer, må jeg nevne noe med hensyn til disse to metodene Og PowerShell 3.0. Mens det er sant at ForEach og Hvor metoder bare ble gjort tilgjengelig I PowerShell 4.0 og senere versjoner, PowerShell 3.0 er fortsatt svært mye brukt i mange miljøer, og med mindre Du bruker PowerShell i et miljø som har standardisert På PowerShell 4.0 og senere, kan du finne deg selv som ønsker at du kan dra nytte av syntaksen fra de nye metodene når Du bruker PowerShell 3.0. Jeg følte at dette var en begrensning verdt å ta opp, så som en del Av TypePx-modulen som jeg nylig publiserte På GitHub og I PowerShell Resource Gallery (aka PowerShellGet public repository, for tiden i begrenset forhåndsvisning), inkluderte Jeg ForEach Og Hvor skriptmetoder som er funksjonelt ekvivalente med metodene introdusert I PowerShell 4.0, slik at du kan utnytte den nye syntaksen og funksjonaliteten selv om Du bruker PowerShell 3.0. Det er noen mangler i denne implementeringen, som jeg vil fremheve senere i denne artikkelen.

ForEach-metoden

ForEach er en metode som lar deg raskt iterere gjennom en samling objekter og ta litt handling på hvert objekt i den samlingen. Denne metoden gir raskere ytelse enn sine eldre kolleger (foreach-setningen og cmdleten ForEach-Object), og det forenkler også noen av de vanligste handlingene du kanskje vil ta på objektene i samlingen. Alle objekter som sendes ut med denne metoden, returneres i en generisk samling av typesystem.Samling.ObjectModel.Samling1.

det er seks støttede måter du kan påberope denne metoden, og hver av disse vil bli forklart nærmere nedenfor. De støttede argumentene som kan brukes når du bruker foreach-metoden, er som følger:foreach(string propertyName)

  • foreach(string propertyName)
  • ForEach(string propertyName, object newValue)
  • ForEach(string methodName)
  • ForEach(string methodName, object argumenter)
  • merk at disse støttes argument Motstandere, ikke forskjellige overbelastninger tilgjengelig for foreach metoden. Bruk av andre argumentparinger enn disse kan føre til feil som ikke klart identifiserer hva det faktiske problemet er.

    foreach(scriptblock expression) og foreach(scriptblock expression, object arguments)

    hvis du sender et skriptblokkuttrykk inn I foreach-metoden, kan du utføre samme type oppgaver som du ville gjort i en skriptblokk som du ville brukt med foreach-setningen eller cmdleten ForEach-Object. I likhet med Cmdleten foreach-Object refererer også variablene $_ og $PSItem til det gjeldende elementet som behandles. Alle argumenter du oppgir utover det opprinnelige skriptblokkargumentet, brukes som argumenter for skriptblokken. Dette er akkurat som hvordan Parameteren-ArgumentList fungerer på cmdleten ForEach-Object. Her er et eksempel som viser hvordan du kan bruke dette til å utføre en skriptblokk på hvert element i en samling:

    # Get a set of services$services = Get-Service c*# Display the names and display names of all services in the collection$services.foreach{"$($_.Name) ($($_.DisplayName))"}# Select a property name to expand using a script block argument$services.foreach({param($PropertyName); $_.$PropertyName}, 'DisplayName')

    Du har kanskje lagt merke til noe rart om denne syntaksen, fordi jeg ikke viklet skriptblokken selv i parentes. Du kan pakke den inn i runde parenteser, men det er valgfritt I PowerShell 4.0 eller senere fordi PowerShell-parseren ble forbedret for å tillate at parentesene utelates når du påkaller en metode som godtar et enkelt skriptblokkargument. I likhet med foreach-setningen og Cmdleten foreach-Object, aktiveres skriptblokken du oppgir i gjeldende omfang. Det betyr at eventuelle variable oppgaver du gjør inne i den skriptblokken, vil fortsette etter At foreach-metoden er ferdig med å utføre.

    foreach(type convertToType)

    Unik for ForEach-metoden, kan du sende en type inn I foreach-metoden hvis du vil konvertere hvert element i en samling til en annen type. Tenk deg for eksempel at du har en samling objekter, og du vil konvertere disse objektene til strengekvivalenten. Her er hva det ville se ut med ForEach-metoden:

    # Get a collection of processes$processes = Get-Process# Convert the objects in that collection into their string equivalent$processes.foreach()

    Du kunne ha utført den samme oppgaven ved å typecasting samlingen i en rekke type streng (f.eks. Til tross for tidsforskjellen, vil jeg ha en tendens til å foretrekke foreach method syntaks i visse situasjoner hvis det tillater meg å opprettholde eleganse i implementeringen ved å unngå ekstra runde parentes i skriptene jeg skriver.

    foreach(string propertyName)

    I PowerShell 3.0 og senere ble et andre parametersett lagt til ForEach-Object slik at du lettere kan hente verdien av en bestemt egenskap ved å bare passere inn et egenskapsnavn som den eneste parameterverdien for ForEach-Object. Denne bekvemmeligheten har også blitt tilbudt I ForEach-metoden. Her er et eksempel som viser hvordan du kan iterere gjennom en samling og returnere en egenskap av den samlingen:

    # Get all services whose name starts with "w"$services = Get-Service w*# Return the names of those services$services.foreach('Name')

    selvfølgelig siden Versjon 3.0 Av PowerShell, kan du bare påkalle $services.Name for å få navnene på alle tjenester, og det vil fullføre raskere enn ForEach-metoden (selv om du bare vil merke ytelsesforskjellen i svært store samlinger i rekkefølge av hundretusener av objekter); det fungerer imidlertid bare for egenskaper som ikke er på selve samlingen, og det er en syntaks som noen skriptere ikke er komfortable med på grunn av den implisitte naturen til hva kommandoen gjør. Den nye foreach method syntaks gir deg et mer eksplisitt alternativ som har den ekstra fordelen av å være litt mer selvdokumenterende også.

    ForEach(string propertyName, object newValue)

    Ikke bare kan du hente en egenskap på en samling av objekter, du kan også sette en egenskap på en samling av objekter. Dette er funksjonalitet som ikke er tilgjengelig i de andre foreach-ene, med mindre du eksplisitt oppretter skriptblokken for å gjøre det. For å angi egenskapen, oppgir du bare egenskapsnavnet og verdien du vil bruke når du angir den egenskapen, slik:

    # Note, this is not a realistic example# This would be used more commonly on configuration data$services = Get-Service c*# Now change the display names of every service to some new value$services.foreach('DisplayName','Hello')

    På samme måte som oppdrag du vil gjøre ved hjelp av equals-operatøren, Vil PowerShell forsøke å konvertere hva du oppgir som den nye verdien til riktig type for egenskapen som tildeles.

    ForEach(strengmetodenavn) og foreach(strengmetodenavn, objektargumenter)

    for å påkalle en metode, oppgir du bare metodenavnet som det første argumentet, og deretter argumentene for den metoden som den andre, tredje, fjerde, etc. argument. Hvis metoden ikke tar noen argumenter, kan du bare passere i metodenavnet, og det vil bli påberopt uten noen argumenter. Her er et eksempel som viser hvordan du kan drepe en rekke prosesser som kjører et bestemt program:

    # Get all processes running Chrome$processes = Get-Process -Name Chrome# Now kill all of those processes$processes.foreach('Kill')

    her er et annet eksempel, denne gangen ved å bruke en metode med argumenter mens du viser hvordan du kan bekrefte at kommandoer følger beste praksis ved å bruke passende navn og aliaser for vanlige parametere:

    # Get all commands that have a ComputerName parameter$cmds = Get-Command -ParameterName ComputerName# Now show a table making sure the parameter names and aliases are consistent$cmds.foreach('ResolveParameter','ComputerName') | Format-Table Name,Aliases

    Som du kan se fra disse resultatene, er det definitivt noen inkonsekvenser i implementeringen Av Datamaskinnavnparametere som bør korrigeres.

    som dekker all funksjonalitet som for Øyeblikket er tilgjengelig i foreach-metoden. Som du kan se, er det ikke mye ny funksjonalitet som tilbys i denne metoden, men syntaksforbedringene når du utfører en enkel oppgave på en samling objekter, er fine, og foreach-metoden ytelsesforbedringer i forhold til tilsvarende foreach-setning for foreach-Object pipeline er definitivt en velkommen forbedring også. Med den forklaringen ut av veien, la Oss gå Videre Til Where-metoden.

    Where-metoden

    Where er en metode som lar deg filtrere en samling objekter. Dette ligner Veldig På Where-Object-cmdleten, Men Where-metoden er Også Som Select-Object Og Group-Object også, inneholder flere tilleggsfunksjoner som Where-Object-cmdleten ikke støtter av seg selv. Denne metoden gir raskere ytelse Enn Where-Object i en enkel, elegant kommando. Som ForEach-metoden returneres alle objekter som sendes ut med denne metoden i en generisk samling av typesystem.Samling.ObjectModel.Samling1.

    det er bare en versjon av denne metoden, som kan beskrives som følger:

    Where(scriptblock expression])

    som angitt av hakeparentesene, er uttrykksskriptblokken nødvendig, og modusopptellingen og numberToReturn heltallargumentet er valgfrie, slik at du kan påkalle denne metoden ved hjelp av 1, 2 eller 3 argumenter. Hvis du vil bruke et bestemt argument, må du angi alle argumenter til venstre for det argumentet(dvs. hvis du vil gi en verdi for numberToReturn, må du også angi verdier for modus og uttrykk).

    Hvor (scriptblock expression)

    Den mest grunnleggende påkallingen Av Where-metoden tar bare et skriptblokkuttrykk som et argument. Skriptblokkuttrykket evalueres en gang for hvert objekt i samlingen som behandles, og hvis det returnerer sant, returneres objektet Med Where-metoden. Dette er den funksjonelle ekvivalenten til å kalle Where-Object cmdleten og sende den en skriptblokk. Som Where-Object-cmdleten kan $ _ og $ PSItem-variablene brukes til å referere til det gjeldende elementet som behandles mens du er inne i skriptblokken.

    her er et veldig enkelt eksempel, som viser hvordan du kan få en liste over kjørende tjenester.

    # Get all services$services = Get-Service# Now filter out any services that are not running$services.where{$_.Status -eq 'Running'}

    Dette gir ingen ny funksjonalitet, men det gir mye raskere ytelse Enn Where-Object og syntaksen er ganske lett å følge, så du bør virkelig vurdere dette for skriptene dine når du utfører klientsidefiltrering av samlinger som du har lagret i en variabel.

    Hvor (scriptblock expression, WhereOperatorSelectionMode mode)

    når du begynner å se på de valgfrie parametrene For Where-metoden, begynner ting å bli mye mer interessant. Windows PowerShell versjon 4.0 inkluderte en ny opplisting med et typenavn På System.Management.Automatisering.WhereOperatorSelectionMode. Merk suffikset av den typennavn: «SelectionMode». Den brukes til å gi kraftige utvalg evner I En where syntaks. Her er verdiene som inngår i denne opptellingen, sammen med deres definisjoner:

    Standard Første Returner de første n-objektene som passerer filteret for uttrykksskriptblokkering, som standard til bare 1 objekt hvis et bestemt antall ikke ble forespurt i numberToReturn. Siste Returner de siste n-objektene som passerer skriptblokkfilteret for uttrykk, som standard til bare 1 objekt hvis et bestemt antall ikke ble forespurt i numberToReturn. SkipUntil Hopp over objekter i samlingen til et objekt passerer uttrykksskriptblokkfilteret, og returner deretter De Første n-objektene, som standard til alle gjenværende objekter hvis det ikke ble oppgitt maksimalt antall i numberToReturn. Til Returner de første n-objektene i en samling til et objekt passerer uttrykksskriptblokkfilteret, og misligholder alle objekter som fører opp til det første objektet som passerte hvis ingen maksimal telling ble oppgitt i numberToReturn. Split Del en samling i to, plassere alle objekter som passerer uttrykket script block filter inn i den første samlingen opp til en maksimal telling hvis en ble gitt i numberToReturn, eller alle objekter som passerer hvis ingen maksimal telling ble gitt, og plassere alle andre objekter som ikke er satt i den første samlingen inn i den andre samlingen.samling.

    Hver av disse gir en unik verdi når du behandler samlinger av data, så jeg gir flere detaljer om hver valgmodus nedenfor.

    Standard

    ikke overraskende er standardverdien til modus-argumentet ‘Standard’. Standard valgmodus tilbyr samme funksjonalitet som du får når du ikke gir en valgmodus i det hele tatt. For eksempel kunne vi ha skrevet den siste linjen i vårt tidligere eksempel som dette:

    # Now filter out any services that are not running$services.where({$_.Status -eq 'Running'},'Default')

    i dette eksemplet er det ekstra argumentet ikke nødvendig, fordi det gjør akkurat det samme som det ville gjøre hvis du ikke oppgav argumentet. Du kan også gi maksimalt antall objekter du vil returnere mens Du bruker Standardvalgsmodus ved hjelp av numberToReturn-argumentet, slik:

    # Get the first 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'Default',10)

    det er viktig å merke seg at eksakt funksjonalitet også er tilgjengelig når Du bruker Den Første valgmodusen (som vi snakker om i et øyeblikk), så det er egentlig ikke praktisk å bruke noen av de valgfrie parametrene i Det hele tatt når Du bruker Standardvalgsmodus.

    Først

    Som du kanskje har gjettet, Lar Den Første valgmodusen deg velge det første objektet(e) i samlingen som passerer skriptblokkuttrykksfilteret. Når Du bruker Først uten en verdi for numberToReturn-argumentet, eller når Du bruker Først med en verdi på 0 for numberToReturn-argumentet, returneres bare det første objektet som passerer filteret. Du kan eventuelt angi hvor mange objekter som skal returneres i numberToReturn-argumentet, i så fall at mange objekter vil bli returnert (forutsatt at det er så mange objekter som passerer filteret).

    her er noen eksempler på bruk av vår tjenestesamling som viser Den Første valgmodusen i aksjon:

    # Get the first service in our collection that is running$services.where({$_.Status -eq 'Running'},'First')# Get the first service in our collection that is running$services.where({$_.Status -eq 'Running'},'First',1)# Get the first 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'First',10)

    Merk at den andre kommandoen i disse eksemplene returnerer de samme resultatene som den første kommandoen fordi den bare eksplisitt passerer i standardverdien til numberToReturn-argumentet når Den Første valgmodusen brukes.

    Siste

    Den Siste valgmodusen fungerer omtrent som Den Første valgmodusen, slik at du kan velge de siste objektene i samlingen som passerer skriptblokkuttrykksfilteret. Når Du bruker Sist uten en verdi for numberToReturn-argumentet, eller Når Du bruker Sist med en verdi på 0 for numberToReturn-argumentet, returneres bare det siste objektet som passerer filteret. Du kan eventuelt angi hvor mange objekter som skal returneres i numberToReturn-argumentet, i så fall at mange objekter vil bli returnert (forutsatt at det er så mange objekter som passerer filteret).

    her er noen eksempler på bruk av vår tjenestesamling som viser siste valgmodus i aksjon:

    # Get the last service in our collection that is running$services.where({$_.Status -eq 'Running'},'Last')# Get the last service in our collection that is running$services.where({$_.Status -eq 'Running'},'Last',1)# Get the last 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'Last',10)

    også som de første utvalgsmoduseksemplene, returnerer den andre kommandoen i disse eksemplene de samme resultatene som den første kommandoen fordi den bare passerer eksplisitt i standardverdien til numberToReturn-argumentet når Den Siste valgmodusen brukes.

    SkipUntil

    SkipUntil-valgmodusen lar deg hoppe over alle objekter i en samling til du finner en som passerer skriptblokkuttrykksfilteret. Når du finner et objekt som passerer filteret, Vil SkipUntil-modus enten returnere alle objekter som er igjen i samlingen hvis ingen verdi eller en verdi på 0 ble gitt til numberToReturn-argumentet, eller det vil returnere de Første N gjenværende objektene i samlingen hvis en verdi større enn null ble gitt til numberToReturn-argumentet. I begge tilfeller vil resultatene inkludere det første objektet som passerte filteret.

    her er noen eksempler ved å bruke et delsett av vår tjenestesamling for å vise SkipUntil-valgmodusen i aksjon:

    # Get a collection of services whose name starts with "c"$services = Get-Service c*# Skip all services until we find one with a status of "Running"$services.where({$_.Status -eq 'Running'},'SkipUntil')# Skip all services until we find one with a status of "Running", then# return the first 2$services.where({$_.Status -eq 'Running'},'SkipUntil',2)

    Til

    Til valgmodus gir motsatt funksjonalitet I SkipUntil valgmodus. Den lar deg returnere objekter i en samling til du finner en som passerer skriptet blokk uttrykk filter. Når du finner et objekt som passerer filteret, Stopper Where-metoden å behandle objekter. Hvis du ikke angir en verdi for numberToReturn-argumentet, eller hvis du angir en verdi på 0, Returnerer Modusen Til valg alle objekter i samlingen som leder opp til den første som passerer skriptblokkuttrykksfilteret. Hvis du angir en verdi for numberToReturn-argumentet som er større enn 0, Vil Modusen Til valg returnere maksimalt antall objekter, noe som betyr at det kanskje ikke engang finner et objekt som passerer skriptblokkuttrykksfilteret.

    her er noen eksempler som bruker et annet delsett av vår tjenestesamling for å vise til valgmodus i aksjon:

    # Get a collection of services whose name starts with "p"$services = Get-Service p*# Return all services until we find one with a status of "Stopped"$services.where({$_.Status -eq 'Stopped'},'Until')# Return the first 2 services unless we find one with a status of# "Stopped" first$services.where({$_.Status -eq 'Stopped'},'Until',2)

    Split

    Split valgmodus er unik. I stedet for å returnere et delsett av samlingen du starter med i en ny samling, returnerer den en ny samling som internt inneholder to separate samlinger. Hva de nestede samlingene inneholder, avhenger av Hvordan Du bruker delt utvalgsmodus. Split lar deg dele en samling av objekter i to. Hvis Du som standard ikke angir en verdi for numberToReturn-argumentet, eller Hvis Du angir en verdi på 0 for numberToReturn-argumentet, plasserer Split alle objekter som sender skriptblokkuttrykksfilteret til den første nestede samlingen, og alle andre objekter (de som ikke sender skriptblokkuttrykksfilteret) til den andre nestede samlingen. Hvis du oppgir en verdi som er større enn 0 for numberToReturn-argumentet, vil split begrense størrelsen på den første samlingen til det maksimale beløpet, og alle gjenværende objekter i samlingen, selv de som samsvarer med skriptblokkuttrykksfilteret, vil bli plassert i den andre samlingen.

    her er noen eksempler som viser Hvordan Delt utvalgsmodus kan brukes til å dele opp en samling objekter på forskjellige måter:

    # Get all services$services = Get-Service# Split the services into two groups: Running and not Running$running,$notRunning = $services.Where({$_.Status -eq 'Running'},'Split')# Show the Running services$running# Show the services that are not Running$notRunning# Split the services into the same two groups, but limit the Running group# to a maximum of 10 items$10running,$others = $services.Where({$_.Status -eq 'Running'},'Split',10)# Show the first 10 Running services$10running# Show all other services$others

    Som du kan se fra dette eksemplet, Er Split ganske kraftig valgmodus, og gir en blanding av filtrering, gruppering og utvalg i en enkelt kommandosamtale.denne samlingen av valgmoduser gjør Where-metoden rask og elegant, men samtidig kraftigere enn Where-Object, Group-Object og Select-Object kombinert i en enkelt rørledning. Hva er ikke å elske om det?

    Mangler I ForEach og Hvor skriptmetoder i TypePx

    som jeg nevnte tidligere i denne artikkelen, har jeg skrevet type extensions For PowerShell 3.0 og senere og pakket dem opp i en modul som heter TypePx. TypePx er en skriptmodul som ble skrevet helt I PowerShell, og den kjører På PowerShell 3.0 eller senere. Hvis Du bruker PowerShell 3.0 (og bare hvis Du bruker PowerShell 3.0), Definerer TypePx foreach Og Hvor skriptmetoder som etterligner oppførselen Til ForEach og hvor metoder I PowerShell 4.0 og senere. Mens det utvidede typesystemet I PowerShell gjør det mulig å etterligne denne oppførselen, er det noen mangler på grunn av at implementeringen er I PowerShell som påvirket hvor langt jeg kunne gå med disse typeutvidelsene. Denne delen beskriver noen av forskjellene og begrensningene som finnes i Foreach Og Where script-metoder I TypePx som du kanskje vil være oppmerksom på hvis Du bruker PowerShell 3.0.

    Skriptblokker som startes fra en skriptmetode, kjøres i et underordnet omfang

    I Motsetning Til ForEach og hvor metoder implementeres som En Del Av PowerShell 4.0 eller senere som påberoper uttrykksskriptblokken i det gjeldende området der metoden kalles, foreach og Hvor skriptmetoder implementert I PowerShell 3.0 påberoper uttrykksskriptblokken i et underordnet område. Dette er en begrensning I PowerShell som har vært der siden begynnelsen (en begrensning, jeg kan legge til, som jeg tror er langt Den største mangelen På PowerShell som språk).

    på grunn av denne begrensningen, vil alle variabler som du tilordner inne i en uttrykksskriptblokk, bare bli endret i det underordnede området. Dette har implikasjoner hvis expression script block er ment å oppdatere en variabel i omfanget der du starter ForEach eller Where. Det er usannsynlig at dette vil forårsake et problem mens Du bruker Where fordi det ikke er veldig vanlig å endre variabler I En Where expression script-blokk, men i ForEach script blocks kan dette utgjøre et problem, så du må huske på dette hvis du bruker disse utvidelsene.

    jeg bør merke meg at jeg vil fjerne denne begrensningen helt, og jeg tror jeg vil kunne gjøre det, men da jeg skrev denne artikkelen, har jeg ennå ikke implementert en løsning for dette.

    De Fleste, men ikke alle samlinger vil ha ForEach og hvor metoder

    I PowerShell 4.0 og senere, ForEach og Hvor metoder er magisk gjort tilgjengelig for alle typer som implementerer IEnumerable unntatt Streng, XmlNode og typer som implementerer IDictionary. I PowerShell tillater det utvidede typesystemet ikke utvidelser som skal opprettes for grensesnitt, bare for typer. Dette er en utfordring hvis du vil lage en bred utvidelse som ForEach og Hvor. I den nåværende implementeringen av disse utvidelsene I TypePx finner typepx-modulen alle typer i alle samlinger lastet i det nåværende app-domenet, og for alle ikke-generiske typer som definerer IEnumerable men ikke IDictionary (unntatt Streng og XmlNode), pluss for alle generiske typer som definerer IEnumerable men ikke IDictionary for generiske samlinger Av PSObject, Object, String, Int32 eller Int64, ForEach og Hvor skriptmetoder vil bli opprettet.

    dette dekker et stort antall typer som i min egen testing har vært tilstrekkelig, men du kan komme inn i typer der du vil bruke disse metodene, og de er ikke tilgjengelige. Hvis det er tilfelle, gi meg beskjed gjennom GitHub, og jeg vil se hva jeg kan gjøre. Dette er også en begrensning jeg vil fjerne, men jeg trenger mer tid til å undersøke hvordan jeg implementerer tilsvarende funksjonalitet i en kompilert samling der jeg kanskje kan definere den mer som den er definert I PowerShell 4.0 og senere.

    PowerShell-skript er ikke like raske som kompilert kode

    dette er sannsynligvis en selvfølge, men når du skriver Noe I PowerShell, som er et tolket språk, vil det ikke løpe så fort som det ville hvis du skrev tilsvarende logikk på et språk Som C#. Dette er absolutt tilfelle for ForEach Og Hvor script metoder, som internt bruker ForEach-Objekt, Hvor-Objekt, og pipelining å etterligne oppførselen til de innfødte foreach og Hvor metoder. I dette tilfellet kommer fordelen av å ha disse kommandoene fra den elegante syntaksen og funksjonaliteten de gir, pluss å kunne bruke disse i skript For PowerShell 3.0 og 4.0. Ytelsesfordelene i ForEach og Hvor er bare I PowerShell 4.0 native implementering.

    PowerShell 3.0 krever parentes rundt alle metodeparametere

    jeg nevnte i eksemplene ovenfor at jeg var i stand til å påkalle en metode med en enkelt litteral skriptblokkparameter uten å pakke den bokstavelige skriptblokken i flere parenteser. Denne funksjonen finnes bare I PowerShell 4.0 eller senere på grunn av forbedringer som ble gjort til parseren i den utgivelsen. I PowerShell 3.0 støtter parseren ikke dette, så parentes er alltid nødvendig for At foreach og Hvor skriptmetoder skal fungere med en enkelt litteral skriptblokkparameter i den versjonen.

    Konklusjon

    da jeg begynte å prøve å etterligne oppførselen Til ForEach og hvor magiske metoder I PowerShell 3.0, skjønte jeg ikke helt hvor mye funksjonalitet de ga. Å grave inn i de tekniske detaljene bak disse metodene, slik at jeg kunne lage utvidelsene jeg ønsket I TypePx, bidro til å avdekke alle de skjulte funksjonene i disse svært kraftige metodene, og jeg er veldig glad for å dele dem med deg i denne artikkelen. Jeg håper denne informasjonen hjelper deg med å utnytte dette fantastiske nye settet med funksjoner I PowerShell-arbeidet ditt, selv om Du fortsatt bruker PowerShell 3.0. Glad skripting!