Guide/Infrastruktur2.0

Infrastruktur 2.0 – en liten guide

Posted by ragnar harper on

Nå som ferien er over er det vel på tide å få skrevet litt igjen. Jeg har de siste to årene jobbet mye med det jeg kaller “Infrastruktur 2.0”, og jeg har tenkt å skrive en liten artikkel serie om dette.

IT-industrien har vært igjennom en del endringer også tidligere, og denne gangen skjer det virkelig ett paradigmeskifte. Jeg tenker selvsagt på nettskyen. Skal du jobbe i IT de kommende årene bør du sette deg grundig inn i nettskyen. (og Powershell bør du uansett beherske….)

Infrastruktur 2.0 handler om hvordan vi bygger en infrastruktur som er dynamisk og fleksibel, gir oss frigjøring fra fysisk lokasjon, samt støtter IT-løsninger lokalt, hos partnere og i nettskyen. De fleste kommer til å få hybrider – hvor de har løsninger kjørende flere steder.

Med en slik endring i tilnærming må vi også endre hvordan vi designer og implementerer grunnleggende komponenter i vår infrastruktur. Virtualisering er selvsagt en viktig egenskap for ditt datasenter – det samme gjelder automatisering og brukervennlige løsninger fjernadgang til ditt datasenter.  Vi må også strekke identiteten vår ut i nettskyen og til partnere, vi må ivareta informasjonsflyt mellom applikasjoner som kjører i ulike datasentre – og vi må sørge for informasjonssikkerhet uavhengig av den fysiske lokasjon til informasjonen.

Jeg tenker å ta for meg de siste elementene i denne serien – integrasjon mellom tjenestene, identitet og informasjonssikkerhet. Mitt fokus kommer til å ligge rundt Microsoft sine produkter og løsninger.

Powershell/Sikkerhet

Noen tanker rundt sikkerhet, Powershell og skuespill

Posted by ragnar harper on

Det er med forundring jeg iaktar sikkerhetsteateret som fortsatt spilles i programvareindustrien. For eksempel selges kryptering fortsatt som en magisk formel som sikrer sikkerhet, og jo større nøkkellengde, jo bedre. De matematiske egenskapene som krypteringen hviler på er sjelden de reelle utfordringene som sikkerheten faktisk møter. Det er i selve implementeringen av sikkerhet at vi feiler. I implementeringen av kryptering – ikke i det matematiske grunnlaget for kryptering. Det spiller derfor sjelden en stor rolle om krypteringen er 128, 256 eller 512 bits – så lenge man kan gå rundt.

Om du låser døra med verdens beste låser – hva betyr vel det så lenge du lar vinduet stå åpent?

Sagt på en annen måte, det hjelper ikke hvor tykk døra er når vinduet står åpent.

Det er lett å glemme , men uansett like viktig, at sikkerheten aldri blir bedre enn det dårligste leddet i en kjede av elementer. I den virkelige verden er det enda lettere å faktisk oppdage at vinduet står oppe, enn det er i den virtuelle verden.

I den virkelige verden hvor man har behov for høy sikkerhet er det mange problemstillinger som ødelegger muligheten for maksimal sikkerhet. Elementer som brukervennlighet, bakoverkompabilitet og ytelse kommer ofte, eller alltid, foran sikkerhet.

Istedet konsentrerer vi sikkerhet rundt et teaterstykke, hvor vi “føler” oss trygge. Vi skaper en illusjon om at noe er sikkert. I programvare versjonen av dette teaterstykket er begrep som nøkkellengde viktig. Andre ting vi føler er utrygt er hashingalgoritmer, på grunn av “birthday” syndromet som disse har. Vi gidder ikke ta innover oss den faktiske reelle betydningen av problemstillingene, da disse ikke passer inn i teaterstykket.

For å kunne vurdere elementer mot hverandre er av vi avhengige av måleparametre. Dette gjelder også sikkerhet. Vi ønsker å måle den eksakte graden av sikkerhet, slik at dette kan være med i vår vurdering. I denne hunger etter falsk informasjon, blir det gjort snarveier. En av disse er at nøkkellengden og algoritmen benyttet til kryptering er en sannferdig beskrivelse av sikkerheten i ett system. Dette er kun for markedsføring, og har ingen reell betydningen for den faktiske sikkerheten en løsning innehar. Ok, la oss fortsette til det jeg egentlig ville skrive om:

En av de andre stykkene som spilles på dette teateret er av leverandører av sikkerhetsprogramvare. Disse gjør desperate stunt for å si noe om sikkerheten til ett system, og prøver alt de kan for at du skal kjøpe disse forsvarsmekanismene. I sommer har dette tatt en forunderlig vending. På BlackHat konferansen i Las Vegas har to personer demonsterert hvordan Powershell er et kraftfullt shell for Windows. De har demonstrert at dette shellet også kan utnyttes for ondsinnede handlinger. De ser styrken i Powershell, og demonsterer at man kan gjøre farlige kommandoer med automatisering. Foredragsholderne har en ganske edruelig holdning til Powershell og sikkerhet – men det gjøres ett par stunt for å få deltakere til sesjonen.

En sikkerhetsleverandør (hvis navn ikke skal nevnes her) demonstrerer nå sin kraftige inkompetanse på sikkerhet generellt og Powershell spesiellt. De hevder at det er utgikk en “0-day exploit” for Powershell, og at de sikrer mot denne. I tillegg beskriver de “ExecutionPolicy” i Powershell som en sikkerhetsteknologi – noe det aldri har vært, og aldri tillagt egenskapen som fra Microsoft. ExecutionPolicy i Powershell er en flott løsning for å unngå kjøring av ad-hoc script ved en misforståelse. ExecutionPolicy hindrer deg ikke i å kjøre kommandoer – kun rettigheter i systemet nekter deg det. Selv om du har ExecutionPolicy satt til “Restricted”kan du kjøre en hvilken som helst kommando – dog får du ikke startet og kjørt .ps1 filer direkte fra kommandolinjen. Det betyr at alle kommandoene i scriptet kan kjøres, og du kan ganske enkelt laste inn alle kommandoene i en fil, og utføre denne, linje for linje med for eksempel Invoke-Expression cmdlet.

Alle som har satt seg nogenlunde inn i Powershell har fått med seg dette. Man skulle anta att en sikkerhetsleverandøre som leverer sikkerhet som også “omfatter” Powershell, også hadde tatt seg bryet med å forstå grunnleggende elementer av Powershell.

Problemet er at mange leser kun overskrifter av det som skrives på Internett – og – ikke bli overrasket nå – tror på det de leser.Selv om en hel artikkel er feil, kan denne lett referes til som en sannhet. Det provoserer når noen søker å selge produkter du ikke trenger, for å beskytte deg mot en trussel som ikke finnes. Mange selskaper som selger sikkerhet selger sikkerhetsprodukter du ikke trenger, fordi du tenker “det skader ikke å være på den sikre siden”. Men hva er den sikre siden i slike tilfeller? Hva med risikoen slike programmer kan innføre i? Når ett selskap tar lett på sannheten, og ikke setter seg godt nok inn i det de søker å beskytte deg mot – hvor mye har de da å tilføre av sikkerhet med sine produkter?

Vi vil alltid erkjenne forsvarerens dilemma – som forsvarer må vi sikre og forsvare alle elementene i vår løsning. Som angriper derimot trenger vi å kun finne ett svakt punkt.

Desverre finnes det digitale kvakksalvere anno 2010 som selger deg noe du ikke trenger, ja, som faktisk kan gjøre ting værre.

Det er dessverre vanskelig for de som ikke jobber med sikkerhet og avdekke disse (faktisk også for de som jobber med sikkerhet).

Guide/Powershell

Kom igang med Powershell – del 7 – Administrasjon av Windows

Posted by ragnar harper on

Dette er artikkel 7 i min Kom igang med Powershell guide og omhandler administrasjon av Windows.

Tidligere artikler har vært:

Del 6 : Feilsøking og debugging
Del 5 : Formatering og gruppering
Del 4 : Utvikle script med Powershell
Del 3 : Sikkerhet i Powershell
Del 2 : Basis Powershell kunnskap (2/2)
Del 1 : Basis Powershell kunnskap (1/2)

Håndtering av filer og kataloger

Ofte får man behov for å håndtere filer og kataloger med script. Vi skal her se på de vanlige behovene for opprettelse, lesing og sletting av filer og kataloger.

Opprettelse av filer og kataloger

Vi starter med opprettelse av fil:

New-item mintekstfil.txt –type File –Value ”Dette er fila mi”

Kjøringen av kommandoen feiler hvis fila finnes fra før. Hvis man ønsker å overskrive fila (hvis den finnes fra før) så bruker man parameteren –force.

New-Item mintekstfil.txt –type File –value “Skriver over..” –force

Hvis du ønsker å opprette en katalog istedet, så går du frem på omtrent samme måte:

New-Item MinKatalog –type Directory

Vi kan bruke –Path hvis vi ønsker å si klart ifra hvor fila eller katalogen skal opprettes.

New-Item –path c:\logfiles\MinLogg.log –type file

En annen måte å opprette filer på er ved å benytte redirection eller pipelineing. Dette er ofte det raskeste hvis vi ønsker at resultatet av en kommando eller operasjon skal inn i ei fil.

La oss lage ei fil med alle skriverne som er definert på maskinen (på en linje):

Get-WmiObject win32_printer | format-table Name,PrinterStatus > printerliste.txt

I kommandoen over benytter vi > til å skrive resultatet til fil. Enkel > oppretter fila, og skriver til den. Hvis fila finnes fra før, overskrives fila. Andre ganger har vi behov for å skrive til ei fil som finnes, og legge data eksisterende innhold. Dette kan vi benytte >> til. Ved å benytte >> opprettes også fila hvis den ikke finnes fra tidligere.

Tenk at du skal lage en logg som viser hver gang et script er kjørt:

Get-Date >> ScriptLogg.log

En del script ønsker man å ta tiden på, og skrive dette til en loggfil.

$start = Get-Date
# utfør script
$stopp = Get-Date
$stopp.Subtract($start) | format-table Days,Hours,Minutes,Seconds,Milliseconds >> ScriptLogg.log

Den siste linjen trekker starttidspunktet fra sluttidspunktet, og skriver resultatet til fila scriptlogg.log. Merk at linja som starter med $stopp.Subtract skal skrives på en linje.

Ok, dette kan også gjøres enklere med kommandoen Measure-Command :

Measure-Command {dir c: -recurse }
Lesing av filer

Mange script må lese inn filerog håndtere disse videre. Get-Content gjør dette for oss:

Get-content tekstfil.txt

Hvis vi ønsker å vise et bestemt antall linjer fra fil benytter vi –TotalCount parameteren.

Get-Content c:\serverlist.txt –TotalCount 5

Kommandoen over henter frem de første fem linjene av fila, og skriver disse ut. En annen måte å gjøre dette på er å benytte Select-Object CmdLet’en. Denne tilbyr mer funksjonalitet, også muligheten for å vise et bestemt antall linjer fra bunnen(slutten) av fila.

Get-Content c:\serverlist.txt | Select-object –last 5

Hvis vi med select-object skulle hentet ut de første fem linjene hadde vi benyttet -first istedet for -last.

Kopiering av filer

Av og til trenger man også å kopiere filer. Dette utføres med Copy-Item cmdlet’en.

Copy-Item *.log c:\logfiles

Copy-Item har også aliaset copy.

NB! Hvis du prøver å utføre tilsvarende operasjon som Copy *.log *.old så vil ikke PowerShell utføre denne operasjonen for deg! Det funker fint i cmd.exe , men av en eller annen grunn takler ikke PowerShell wildcards og kopiering hvor kildefilene og målfilene ligger i samme mappe.

Her er en workaround for dette problemet:

BulkCopy.ps1

Set-Location “C:\logs”
$files = get-childitem | where { $_.extension –eq “.log” }
Foreach($file in $files)
{
$filename=($file.FullName).ToString()
$arr=@($filename.split(“.”))
$newname=$arr[0]+”.old”
Write-Host “copying “$file.FullName “to” $newname
Copy $file.fullname $newname -force
}
Sletting av filer og kataloger

Til å slette filer og kataloger benytter vi Remove-Item. Hvis du ønsker å slette alle tmp filer i katalogen c:\temp kan du kjøre følgende kommando:

Remove-item c:\temp\*.txt

La oss si at du ønsker å fjerne alle loggfilene som er eldre enn 2006, og at året er en del av navnet:

Remove-Item C:\backup\*.* -recurse –exclude 2006*.log

Du kan også benytte –include. Selv om du på kommandoene finner parameteren –identity, så er ikke dette implementert i første versjon av PowerShell. (Hvis du for eksempel tenke å kjøre kommandoen som en annen enn den som var logget på)

Du sletter kataloger på samme måte som du sletter filer, men til det kan du også benytte aliaset rmdir, slik som sletting av filer har aliasene erase og del.

Rename filer

Det hender også at vi trenger å gi filene nytt navn, og til å gjøre dette har vi kommandoen Rename-Item.

Rename-Item aktivlogg.txt passivlogg.txt

En svakhet med Rename-Item kommandoen er at den heller ikke støtter wildcards. Så på samme måte med BulkCopy.ps1, må vi lage et script som endrer navnet på flere filer i en operasjon:

BulkRename.ps1

Set-Location “C:\Logs”
$files=Get-ChildItem –recurse | Where { $_.extension –eq “.log” }
Foreach ($file in $files)
{
$filename = ($file.name).ToString()
$arr=@($filename.split(“.”))
$newname=$arr[0] + “.old”
Write-Host “renaming “$file.fullname “to “$newname
Rename-item $file.fullname $newname -force
}
Test om filer og baner finnes

Med Test-Path kan vi sjekke om en katalog eller fil finnes. Den returnerer true hvis fila eller katalogen finnes, og false hvis ikke.

Test-Path c:\temp

Håndtering av rettigheter

Ettersom at alle objekter i Windows inneholder en ACL (Access Control List) som styrer tilgangen til objektet, har vi bruk for å kunne scripte disse adgangene. Det betyr for eksempel at vi kan lese av eller sette adgangen til filer,kataloger og registrynøkler.

La oss lese av rettighetene til fila boot.ini som finnes på rota av c:\

get-acl c:\boot.ini

Resultatet av denne kommandoen kan oppleves litt vanskelig å lese, og de fleste vil nok heller benytte følgende kommando:

Get-acl c:\boot.ini | format-list

Kommandoen kan benyttes mot filer, kataloger og registrynøkler. (Og eventuelt andre objekter hvor det finnes en provider som tilbyr dette.) (Kommandoen under er på en linje)

Get-Acl HKLM:\software\microsoft\windows\currentversion\run | format-list

La oss si at du ønsker å hente ut informasjon om hvem som er eier av filer og kataloger på c:\. Dette kan du enkelt hente ut med Get-Acl på følgende måte:

Get-Acl C:\* | format-table Path,Owner -autosize

Ser du nøye på parametrene til kommandoen vil du se at den mangler –recurse. Hvis du ønsker å ta ut rapporten på en mappestruktur (altså ta med undermappene også) kan følgende script kjøres:

GetOwnerReport.ps1

$report = “C:\OwnerReport.csv” #navn på fila som rapporten lagres i
$startingDir = Read-Host “Hvilken katalog vil du starte i?”
Get-ChildItem $startingDir –recurse | Get-Acl | Select Path,Owner | Export-Csv $report –NoTypeInformation
Write-Host “Rapporten er ferdig.”

Å lese rettigheter er enkelt med PowerShell. Dessverre kan vi si at å sette rettigheter ikke er like rett frem i dagens versjon av PowerShell. Faktisk er dette enklere med kommandoer som Cacls og Icacls, og jeg kommer til å demonstere begge mulighetene, så får du velge selv.

Årsaken til at PowerShell kan være vanskelig å bruke til dette er at den krever kunnskap om .NET sikkerhetsmodellen og hvordan en NTFS security descriptor skal bygges opp.

ChangeAcl.ps1

$Right=”FullControl” #rettigheten vi skal gi
$startingDir = Read-Host “Hvilken katalog vil du starte i?”
$principal= Read-Host “Hvilken bruker vil du gi Full Control til?`nBenytt formatet domene\brukernavn eller domene\gruppe”
$rule=new-object System.Security.AccessControl.FileSystemAccessRule ($principal, $right, “Allow”)
Foreach($file in $(Get-ChildItem $startingDir –recurse))
{
$acl=get-acl $file.Fullname
Write-Host –foregroundcolor Yellow $file.Fullname
$acl.SetAccessRule($rule)
Set-acl $file.Fullname $acl
$acl=get-acl $file.Fullname
Write-Host –foregroundcolor Green “Nye rettigheter”
Write-Host $acl.AccessToString `n
}

De verdiene du kunne ha puttet inn I $right variabelen er:

  • ListDirectory
  • ReadData
  • WriteData
  • CreateFiles
  • CreateDirectories
  • AppendData
  • ReadExtendedAttributes
  • WriteExtendedAttributes
  • Traverse
  • ExecuteFile
  • DeleteSubdirectoriesAndFiles
  • ReadAttributes
  • WriteAttributes
  • Write
  • Delete
  • ReadPermissions
  • Read
  • ReadAndExecute
  • Modify
  • ChangePermissions
  • TakeOwnership
  • Synchronize
  • FullControl

Selve jobben som scriptet utfører kan identifiseres i følgende linjer:

$acl=Get-acl $file.Fullname

Deretter legger vi til den nye rettigheten i $acl

$acl.SetAccessRule($rule)

Håndtering av eventlogger

Logger er gull, er et uttrykk jeg benytter ved en del anledninger. Men det kan være vanskelig å finne gullet, og hvordan kommer man til det?

Med PowerShell er det enkelt å jobbe med eventlogger gjennom CmdLet’en Get-EventLog.

For å se hvilke eventlogger du har tilgjenlig kan du kjøre følgende kommando:

Get-EventLog –list

For å hente ut informasjon fra Application kan du kjøre:

Get-EventLog Application

Dette er som regel ikke av interesse å dumpe hele eventloggen uten å filtrere på noen som helst måte.

La oss forsøke å hente ut de fem siste hendelsene:

Get-EventLog Application –newest 5

Ettersom at resultatet skrives ut i tabellformat kan det være avkortet. For å se fullstendig informasjon formaterer vi som liste ved å benytte format-list:

Get-EventLog Application –newest 5 | Format-List

For å filtrere mer kan vi benytte Where. La oss si at vi ønsker å finne en gitt eventid:

Get-EventLog Application | where { $_.eventid –eq 1018}

Hva så hvis vi ønsker å hente ut de fem siste (tidsmessig) hendelsene med eventid 1018?

(kjør neste kommando på ei linje)

Get-EventLog Application | where { $_.eventid –eq 1018 } | select –first 5

Hva hvis du ønsker å skrive ut de fem siste Error meldingene? Type event lagres i feltet EntryType, så da må vi benytte EntryType i where setningen :

Get-EventLog Application | where { $_.EntryType –eq “Error” } | select –first 5

Ønsker du å hente ut advarsler (warnings) bytter du ut Error med Warning:

Get-EventLog Application | where { $_.EntryType –eq “Warning” } | select –first 5

La oss kombinere EntryType og Source (fortsatt skal alt på en linje):

Get-EventLog Application | where { $_.EntryType –eq “Error” –and $_.Source –eq “WinMgmt” }

Eventloggene er også et område hvor regular expressions gjør stor nytte. La oss ta et enkelt søk i System loggen for alle meldinger som inneholder ordet ”disk”:

Get-Eventlog System | where { $_.Message –match ”disk” }

image

Get-Eventlog fungerer fint så lenge scriptet kjøres på den maskinen som du skal lese loggene fra. Men hva hvis du skal hente informasjon fra en annen maskin? Med Powershell 1.0 måtte du da benytte WMI. Powershell 2.0 har fått parameteren –ComputerName også på Get-EVentLog.

Kommandoen kan ta en tid, spesielt hvis det er mange poster i loggen du gjennomgår.

Håndtering av registry

Vi har vel over tid erfart at registry er stedet hvor applikasjoner går inn, og ingen helt vet hva som kommer ut av det. Det er ingen tvil om at selv om .NET skal befri oss fra dll-hell og et overbelastet registry, må vi inn i registry for å gjøre en del oppgaver. Registry er stedet hvor mye lagres, spesielt konfigureringer. En av PowerShells fordeler er at den behandler registry som enhver annen lokasjon eller katalog om du vil. Du kan altså navigere deg inn i registry direkte fra shellet, la oss gå inn i HKEY_LOCAL_MACHINE :

Cd hklm:
dir

Eller hva med HKEY_CURRENT_USER:

Cd hkcu:
dir

La oss se på hvordan vi kan lese informasjon fra registry. Vi kan finne hvilken Windows versjon som er installert, og hvem den er installert til på følgende måte:

$regpath="HKLM:\Software\Microsoft\Windows NT\CurrentVersion"
$regkey=Get-ItemProperty $regpath
$regkey

image

Vi kan selvsagt også angi banen vi skal lese fra direkte:

Get-ItemProperty "hklm:\software\microsoft\windows\currentversion\uninstall\imgburn"

Hvis du ønsker å se verdier der du står, kan du ikke benytte dir (eller Get-ChildItem) til dette. De kommandoene gir deg kun kataloger (eller nøkler) som ligger under området der du står. For å lese av verdiene der du står, benytter du . (punktum) på følgende måte:

Get-ItemPropery .

I tillegg til å lese av verdier trenger vi å endre samt opprette verdier i registry. La oss se på hvordan vi kan endre verdier med Set-ItemProperty.

Set-ItemProperty -path . –name Domain –value ”DittDomene”

MERK! Hvis du kjører Vista med User Account Control aktivert (som er default) krever dette at PowerShell kjører som administrator. Hvis ikke får du feilmelding, med beskjed om at du ikke har rettigheter. For å kjøre PowerShell som administrator høyreklikker du på PowerShell snarveien, og velger Run As Administrator.

For å se om verdien ble satt kan du nå kjøre følgende kommando som kun henter ut verdien til Domain:

(Get-ItemProperty .).Domain

Nå som vi har satt og hentet ut informasjon, la oss opprette en subkey, og opprette noen egenskaper i registry. For å gjøre dette navigerer vi oss til HKEY_CURRENT_USER, HKCU:

Set-Location HKCU:

Nå lager vi en subkey(underkatalog) med navn PowerShell kurs:

New-Item “PowerShell kurs”

Dette kan du nå bekrefte ved å kjøre dir av HKCU:

dir

La oss nå opprette noen verdier under PowerShell kurs, så først navigerer vi inn i PowerShell kurs:

cd “PowerShell kurs”

Deretter oppretter vi egenskapen Leverandør med verdien ”Harper” :

new-itemproperty –path . –name “Leverandør” –value “Harper”

Dette kan du nå enkelt kvalitetsikre med følgende kommando:

Get-ItemProperty .

Som du ser fikk vi nå en verdi av type string. Hvis du ønsker på ha en annen datatype, påvirker du dette med–PropertyType. La oss opprette en ny verdi i registry av typen DWORD:

new-itemproperty –path . –PropertyType DWORD –name ”Aktiv” –value 1

Du kan også endre navnet på ting i registry, på lik linje med i filsystemet. La oss endre navnet på ”PowerShell kurs” til kurs ”PowerShell” :

Jeg starter med å gå til nivået over der jeg står (da jeg står i ”PowerShell kurs” akkurat nå)

cd ..

Deretter benytter jeg Rename-Item (gjennom aliaset ren)

ren ”PowerShell kurs” ”PowerShell”

La oss fullføre registry arbeidet med å rydde opp etter oss (med andre ord, slette det vi har gjort) Jeg starter operasjonen med å gå inn i mappa vi opprettet, og som nå heter PowerShell :

cd PowerShell

Deretter fjerner jeg kun egenskapen Leverandør med følgende kommando:

remove-itemproperty –path . –name ”Leverandør”

Hvis vi ønsker å fjerne hele subkey ”PowerShell” kan vi også gjøre dette ved å gå opp et nivå, og kjøre Remove-Item, som følger:

cd ..
remove-item ”PowerShell”

Håndtering av services

Tilgang til services(tjenester) håndteres i PowerShell av kommandoene Get-Service, Start-Service, Stop-Service, Restart-Service,Suspend-Service, Resume-Service og Set-Service. Disse kommandoene gir oss tilgang til mesteparten av funksjonaliteten vi trenger, bortsett fra å sette konto eller passord til brukeren servicen kjører som.

Vi starter med å liste opp alle services:

Get-Service

Denne kommandoen lister ut alle servicene, uansett tilstanden de er i.

Hvis vi ønsker å liste ut alle med status Running kan vi utføre følgende kommando:

Get-Service | where { $_.status –eq ”Running” }

Vi starter og stopper prosesser med Start-Service og Stop-Service på følgende måte:

Stop-Service wsearch # stopper Windows Search
Start-Service wsearch # starter Windows Search

Hvis man ikke husker navnet på servicen, kan det være man husker ”Display name”, slik som Windows Search for servicen wsearch:

Stop-Service –DisplayName “Windows Search” # stopper Windows Search
Start-Service –DisplayName “Windows Search” # starter Windows Search
Parameteren displayname kan også benyttes sammen med Get-Service:
Get-Service –DisplayName “Windows Search”

Enkelte services (med andre ord – ikke alle) støtter det å bli satt i pause. Dette gjøres på tilsvarende måte som Stop-Service, men med CmdLet Suspend-Service. Med suspend slipper du å starte opp servicen på nytt etterpå, den ”lever” fortsatt, og kan fortsette med Resume-Service.

Vi kan også endre oppstartsoppførselen til en service gjennom Set-Service CmdLet :

Set-Service –name spooler –StartupType Manual

Istedet for Manual kan du også oppgi Automatic og Disabled.

Et annet eksempel som kan være nyttig er å kunne liste ut alle services som ikke kjører, men er satt til automatisk oppstart.

Get-WmiObject Win32_Service |where {$_.State –ne “Running” –and $_.StartMode –eq “Auto”} 

Eksemplet over tester for alle services som ikke har state lik ”Running” (-ne , not equals) og har startmode lik ”Auto” (-eq, equals).

Her benyttes også Get-WmiObject istedet for Get-Service – dette på grunn av at StartMode ikke er tilgjenglig i Get-Process CmdLet. Det viser også styrken til Get-WmiObject – hvis noe ikke er tilgjenglig gjennom Powershells innebygde kommandoer vil du finne det i WMI grensesnittet.

Håndtering av prosesser

Prosesser kan enkelt håndteres gjennom PowerShell med Get-Process CmdLet’en.

Slik lister du ut alle kjørende prosesser på maskina:

Get-Process

Ønsker du å ta en titt på en bestemt process angir du prosessnavnet som argument:

Get-Process calc

Vi kan også enkelt stoppe alle prosessene med navnet calc:

Stop-Process –name calc

Dette stopper alle kjørende forekomster av calc. Noen ganger ønsker vi kun å stoppe en enkelt av dem, og da kan vi benytte Id. Først henter du ut id med Get-Process, deretter kjører du Stop-Process med id.

Stop-Process 3874

Som med andre CmdLet’s for administrasjon, må du også på prosesser benytte WMI. La oss liste ut alle prosessene som kjører på maskinen DC1:

$cred = Get-Credential
Get-WmiObject –class Win32_Process –computer DC1 –credential $cred | Select Name,Handle,VirtualSize,WorkingSetSize | format-table 

Når man jobber med prosesser, spesielt med Stop-Process, kan det være smart å benytte –whatif, slik at man ser hva man gjør, før man utfører det.

Eksempel med –whatif :

Get-Process | Stop-Process -whatif

En annen ting vi skal se på når vi snakker om prosesser er hvordan PowerShell starter prosesser. I og med at Powershell er et shell (i tillegg til scriptspråk) så kan vi starte prosesser direkte fra PowerShell. Hvis du ønsker å kjøre calc.exe fra PowerShell, så skriver du navnet på den kjørbare fila. I dette tilfellet calc.

calc 

Eksemplet viser at kalkulatoren starter, og vi får returnert kontrollen umiddelbart tilbake til Powershell. Dette er fordi at calc.exe er en Win32 GUI (grafisk) prosess, og dermed kjøres i bakgrunnen. Andre kommandoer (ikke-grafiske) krever kjører som regel i samme prosess som PowerShell, og det gjør at vi ikke kan fortsette før kommandoen er fullført. Uansett, noen ganger er det nødvendig å vente til den grafiske applikasjonen er fullført før vi kan fortsette. I cmd.exe gjør vi dette med start /wait, i PowerShell gjør vi det slik:

calc | out-null

Ved å pipe til out-null tvinger vi prosessen til å fullføre før vi kan fortsette.

En annen måte å gjøre dette på er følgende:

$np = get-process notepad
$np.waitforexit()

I eksemplet over tar vi tak i en kjørende prosess, og venter til denne avslutter før vi går videre. Jeg vil også vise et eksempel til, hvor vi tar tak i den navnet på vinduet til den kjørende prosessen:

./filami.txt
$fp = gps | where {$_.mainwindowtitle -match "filami.txt"}
$fp.WaitForExit()

Følgende eksempel viser hvordan du kan benytte get-process til å identifisere applikasjoner som henger, og så avslutte dem med Kill().

Håndtering av Windows Firewall

Gjennom støtten for COM objekt kan man også jobbe mot Windows Firewall med PowerShell. Dette objektet lar deg både lese av innstillinger, samt gjøre konfigurasjonsendringer.

Vi starter med å opprette en variabel av typen HnetCfg.FwMgr. Dette er COM objektet vi benytter for å konfigurere Windows Firewall.

$fw = new-object –com HNetCfg.FwMgr

Sjekk om brannmuren er aktiv:

$fw.LocalPolicy.CurrentProfile.FireWallEnabled

Du kan enkelt aktivere brannmuren om den ikke er aktiv

(på lik linje kan du slå den av med $false):

$fw.LocalPolicy.CurrentProfile.FireWallEnabled = $true

På følgende måte kan du de om noen applikasjoner er autorisert til å gå igjennom brannmuren:

$fw.LocalPolicy.CurrentProfile.AuthorizedApplications

Hvis du ønsker å legge inn en åpning for innkommende trafikk på port 8080, kan du gjøre det på følgende måte:

$port=new-object -com HNetCfg.FWOpenPort
$port.Name="WebDemo"
$port.Port=8080
$port.Protocol=6
$fw.LocalPolicy.CurrentProfile.GloballyOpenPorts.Add($port)

HnetCfg.FWOpenPort er et COM objekt vi benytter for å jobbe med portene på brannmuren. I setningen $port.Protocol=6 står tallet 6 for protokollen TCP. Det betyr altså at vi åpner port 8080 på TCP protokollen.

Tilsvarende kan vi fjerne en åpen port på følgende måte:

(MERK! Dette krever administrator adgang)

$fw.LocalPolicy.CurrentProfile.GloballyOpenPorts.Remove(8080,6)

Man kan også liste åpne porter (tilsvarende netsh firewall show portopening)

$profile = (new-object -com HNetCfg.FwMgr).LocalPolicy.CurrentProfile
$profile.GloballyOpenPorts | ft name,port
Guide/Powershell

Kom igang med Powershell – del 6 – Feilsøking og debugging

Posted by ragnar harper on

Dette er artikkel 6 i min Kom igang med Powershell guide og omhandler feilsøking og debugging i Powershell 1.0 og Powershell 2.0.
Tidligere artikler har vært:

Del 5 : Formatering og gruppering
Del 4 : Utvikle script med Powershell
Del 3 : Sikkerhet i Powershell
Del 2 : Basis Powershell kunnskap (2/2)
Del 1 : Basis Powershell kunnskap (1/2)

Feilsøking og debugging

Noen ganger må vi håndtere feil som oppstår i kjøringen av en CmdLet, eller feil som vi selv er skyld i å innføre. Vi skal her se på hvordan vi kan påvirke hvordan feil skal håndteres.

Håndtering av feil (ErrorAction)

Feil i PowerShell deles inn i to kategorier

  • Terminating Denne type feil stopper scriptet
  • Non-terminating Selv om det har oppstått feil kan scriptet fortsette videre

Feil som oppstår representeres med et eget objekt – ErrorRecord. Dette objektet inneholder en exception som er beskriver årsaken til at feilen har oppstått, i tillegg til å si hvor.

ErrorRecord objektene lagres i en standard variabel med navn $error. $error er en samling med ErrorRecords.

Hvert ErrorRecord objekt inneholder følgende egenskaper:

  • Exception Exception er et eget objekt, med egne egenskaper. Den viktigste er Message som beskriver feilen. (Inneholder feilteksten)
  • TargetObject Dette er objektet hvor feilen oppsto
  • CategoryInfo Er en kategorisering av feil
  • FullyQualifiedErrorId Så spesifikk informasjon som mulig om feilen
  • ErrorDetails Denne er valgfri, så noen ganger er den null. Andre ganger inneholder den feilmeldingen i klartekst på engelsk.
  • InvocationInfo Hvis tilgjengelig, så sier denne deg hvilken linje i scriptet som har feilet, eller hvilken CmdLet. Kan være null.

Eksempel som skriver ut feilbeskrivelse for den siste feilen som har oppstått (error[0]):

$error[0].Exception.Message

De fleste CmdLets lar deg påvirke hvordan de enkle feilene skal håndteres (de som ikke øyeblikkelig stopper scriptet, men hvor det er mulig å fortsette. (non-terminating)). Dette påvirker du igjennom ErrorAction parametret.

Følgende verdier kan benyttes på ErrorAction parametret:

· Continue Dette er default valget, og betyr at feilen blir skrevet ut, men kjøringen fortsetter uansett.

· Stop Dette betyr at kjøringen skal stoppe ved feil

· Inquire Valget stopper kjøringen, og ber brukeren bestemme om kjøringen skal fortsette eller ikke

· SilentlyContinue Kjøringen av scriptet blir ikke avbrutt av feil. Feil blir heller ikke rapportert i resultatet.

Eksempel på bruk av ErrorAction (-ea) parameter:

$a=Get-WmiObject Win32_OperatingSystem –ea stop

Hvordan fange feil i Powershell 1.0?

Når feil oppstår sier vi at et ”unntak blir kastet”, eller ”throw exception”. Med unntak mener vi at det har oppstått en situasjon hvor vanlig planlagt prosessering ikke kan skje. La oss si at vi skal flytte ei fil fra mappe a til mappe b, men at fila ikke finnes. Da kan vi ikke flytte fila, og må kaste et unntak som sier vi ikke fant fila.

Når feil oppstår er det best practice å ta i mot feilen (catch exception), og til å gjøre dette benytter vi en errorhandler. (feilhåndterer).

Mal for en errorhandler

Trap [Exception] {
#håndter feilen, eller gi informativ informasjon
# $_ representerer ErrorRecord som ble kastet
Return [argument] | break | continue
}

I en errorhandler er det to ting som er spesielt viktig å huske. For det første har du informasjon om feilen som har oppstått tilgjengelig i variabelen $_ . Denne variabelen inneholder det ErrorRecord objektet som ble kastet der feilen oppstod. Videre er det viktig å huske at den siste linja i errorhandleren kan være en av tre kommandoer ; Return, Break eller Continue. Med return kan vi returnere verdier, med break kan vi stanse kjøringen, og med continue fortsetter vi uten å returnere noen verdi.

Følgende forklarer hvordan feilhåndtering virker i Powershell: Hvis en errorhandler er definert, blir denne utført når det oppstår feil. Errorhandler har tilgang til variabelen $error som forklarer hva som gikk galt. Den kan også sette ErrorPolicy for å si om scriptet skal fortsette eller ikke (defineres i slutten av errorhandler- slik som break eller continue, eller et hvilket som helst argument av eget ønske). Vi kan også definere en errorhandler til kun å omfatte bestemte typer feil. Dette angir vi direkte etter nøkkelordet Trap.

Her er et enkelt eksempel på en errorhandler:

TrapTest.ps1

function CheckWMI ($computer)
{
trap
{
Write-host “Det oppstod en feil:”
Write-host ”ID: ” $_.ErrorId
Write-host ”Beskrivelse:” $_.Exception.Message
continue
}
$osinfo = get-wmiobject Win32_OperatingSystem –property ServicePackMajorVersion –computer $computer –ea stop
Write-host “Maskin: “ $osinfo.ServicePackMajorVersion
}
Write-host “Sjekker service pack versjoner:”
CheckWMI(”FinnesEi”)
CheckWMI(”FinnesHellerIkke”)

I eksemplet over er det viktig at –ea stop er med. Hvis ikke vil feilen blir håndtert i CmdLet’en, og ikke i ErrorHandleren vi definerte. Du kan selv teste dette ved å fjerne –ea stop (da blir default Continue benyttet som erroraction, og CmdLet Get-WMIObject håndterer feilen selv).

Du kan også kaste feil selv ved å benytte throw:

throw “Noe gikk galt…”

Dette kan du også benytte i errorhandler, for eksempel for å behandle en feil, og sende den videre til neste errorhandler (hvis det er flere definert i overliggende scope)

Trap
{
throw $_
}

Hvordan fange feil med Powershell 2.0?

Powershell 2.0 har fått fullverdig feilhåndtering gjennom try, catch og finally.

Mal for try,catch, finally:

try
{
handlinger
}
catch
{
håndter feil
}
finally
{
rydd opp , f.eks. tilkoblinger du har åpnet som skal lukkes
}

Du må ikke ha med finally om du ikke trenger det.

Om kodeblokken som kjører i try ikke opplever feil vil kodeblokken(e) i catch setningen ikke kjøre. Finally vil kjøres uavhengig om det går bra eller ikke med try.

Vi kan bygge inn flere catch setninger etter hverandre. Vi starter da med de mest spesifikke, og kan avslutte med en generell catch til slutt.

try
{
$wc = new-object System.Net.WebClient
$wc.DownloadFile("http://www.contoso.com/MyDoc.doc")
}
catch [System.Net.WebException],[System.IO.IOException]
{
"Unable to download MyDoc.doc from http://www.contoso.com."
}
catch
{
"An error occurred that could not be resolved."
}

Merk: Finally kjøres selv om du trykker CTRL+C eller har en exit kommando i skriptet.

Debugging med Powershell 1.0

Debugging er antageligvis den mest arbeidssomme og tidkrevende delen av å skrive avanserte script.

I PowerShell versjon 1.0 er det lagt inn muligheter for debugbistand gjennom kommandoen Set-PSDebug. Jeg skal lett innrømme at denne kommandoen ikke er vakker i bruk, men den gir deg funksjonalitet som kan være av interesse når du støter på problemer, eller trenger å kjøre noe stegvis.

Du kan nå teste Set-PSDebug med følgende kommando:

Set-PSDebug -step

Kjør dereretter ett script du har liggende.

Som du ser får du nå anledning til å velge hva du ønsker å gjøre på hver linje. Det valget som er mest av interesse er S for Suspend. Når du trykker S stopper du kjøringen av scriptet, og havner i en kommandolinje sesjon hvor du kan inspisere variabler og endre verdier. Når du er klar til å fortsette skriver du exit, og scriptet vil fortsette å kjøre.

Hvis du ønsker å slå dette av skriver du:

Set-PSDebug -off 

Du kan også velge å kjøre sporing av alt som skjer gjennom parameteren trace. Denne har to alternativer, 1 og 2. Med 1 skriver den ut kodelinjene som utføres, med 2 skriver den også ut variabler som blir satt:

Set-PSDebug –trace 2

Debugging med Powershell 2.0

Med Powershell 2.0 er debugging blitt enklere. Vi har fått mulighet til å sette breakpoints, og med ISE har vi fått ett grafisk grensesnitt som er enklere å forholde seg til under debugging. La oss starte med å se hvordan du kan debugge fra kommandolinjen i Powershell 2.0

Debugging fra kommandolinjen

I Powershell 2.0 bruker vi ikke Set-PSDebug som i Powershell 1.0, men vi benytter Set-PSBreakPoint. Set-PSBreakpoint kan sette breakpoint på linje, cmdlet eller variabel. Vi kan også benytte en scriptblokk, noe som lar oss sette betingelser for ett breakpoint.

Vi starter med å se hvordan vi kan sette breakpoint på en gitt linje i ett skript. Følgende eksempel setter breakpoint på linje 2 i scriptet testscript.ps1:

Set-PSBreakpoint –Script testscript.ps1 –Line 2

Når du nå kjører scriptet vil det stoppe før linje 2 utføres. Du har da mulighet til å bruke egne debugkommandoer. Disse henter du frem ved å skrive h eller ? ved debugprompt.

Kommandoene du har tilgjenglig er:

  • s, stepInto
  • v, stepOver
  • o, stepOut
  • c, Continue
  • q, Quit
  • k, Get-PSCallStack
  • l, list
  • <enter>
  • h, ?

Av disse kommandoene bruker stepInto, stepOver, stepOut , quit og continue for å kontrollere kjøringen av scriptet. Om du ønsker å kjøre linje-for-linje velger du continue. Om du står på en linje som kaller en fuksjon eller ett annet script kan du bestemme om du skal debugge inn i funksjonen eller scriptet med stepInto og stepOver. StepInto tar deg inn i funsjonen eller scriptet, og stepOver utfører funksjonen eller scriptet, før den igjen stopper på neste linje i scriptet du allerde er i. StepOut kjører deg ut av funksjonen eller skriptet du nå er i. Quit avslutter kjøringen (og dermed også debuggingen) . Enter benyttes for å gjenta forrige valgte kommando.

image

Du kan også angi Actions som skal kjøres når ett breakpoint er aktivert. Dette gjør du med –Action paramteren. På Set-PSBreakpoint. I eksemplet under ser du at den ikke stopper når navnet er lik Pelle, men kun når navnet er lik Ragnar.

image

Se callstack under debugging

Ved debugprompten kan du se callstack for hvor du er med kommandoen k (ellet Get-PSCallStack). Det siste utførte steget er øverst, og det første er nederst i stakken. På eksemplet under ser du at sesjonen startet fra kommandolinjen (prompt) og vi står nå i scriptet testscript.ps1 på linje 2.

image

Debugging med Powershell ISE

For de fleste er Powershell ISE det enkleste stedet å utføre debugging. Last inn scriptet, og trykk F9 på linjen du ønsker å plassere ett breakpoint. I Powershell ISE har du en egen meny “Debug” hvor du kan se hvilke alternativer som er tilgjenglig. Powershell ISE har også egne tastatursnarveier for å kontrollere kjøringen av scriptet.

Step Over = F10

Step Into = F11

Step Out = Shift+F11

Run / Continue = F5

Stop Debugger = Shift + F5

Angi/fjerne Breakpoint = F9

Fjerne alle breakpoints = Ctrl+Shift+F9

Liste breakpoints = Ctrl+Shift+L

Vise callstack = Ctrl+Shift+D

 

image

En annen fin detalj er at ved å holde musmarkøren over en variabel vil de se innholdet av variabelen. På eksemplet under holder jeg musmarkøren over $Navn og får opp innholdet er lik Ragnar

image

Vi har i denne artikkelen sett litt på debugging og feilsøking i Powershell – med vekt på Powershell 2.0 og hva som er nytt der.

Guide/Powershell

Kom igang med Powershell – del 5 – Formatering, gruppering og eksport

Posted by ragnar harper on

Du finner de foregående delene av Kom igang med Powershell her:

Del 1 – Grunnleggende navigasjon og kommandoer

Del 2 – Grunnleggende navigasjon og kommandoer fortsetter

Del 3 – Sikkerhet og signering av script

Del 4 – Utvikle script

Sende data ut fra Powershell

Vi kikket kort på redirection i del 1, og skal her se på litt mer avanserte muligheter. Merk at PowerShell ikke støtter redirection inn til kommandoer (der bruker du pipeline). Pipelining og redirection hører tett sammen.

Du kan enkelt styre data ut dit du vil ved å pipe data til out kommandoene i PowerShell. Du har blant annet følgende out kommandoer:

  • Out-printer
  • Out-file
  • Out-null

Hvis du ønsker å skrive ut resultatet av en operasjon kan du ganske enkelt benytte følgende :

Dir | out-printer

Hvis du istedet ønsker å kjøre det til fil

Dir | out-file filnavn.txt

Formatering

Istedet for at hver kommando skal inneholde formateringskode benytter PowerShell seg av muligheten for å pipe resultatet til egne formateringskommandoer. Ettersom at PowerShell benytter seg objekter, har vi rike muligheter til å tilpasse og formatere utdataene med egne kommandoer. Formateringskommandoene starter med Format- , og de du kommer til å bruke mest er nok Format-List og Format-Table. Hva som er standard formatering bestemmes av CmdLet, og det varierer om det er Format-List eller Format-Table.

Format-List

Format-List gir deg resultatet som en liste, og ikke som en tabell. Det betyr at hvert objekt skrives ut med utvalgte egenskapene (eller de du velger) i en liste.

Se på følgende eksempel:

image

Som du ser av eksemplet over grupperes alle objektene adskilt med linjeskift. For hvert objekt skrives utvalgte egenskaper på egne linjer. Dette er god egnet for å skrive ut felt med mye informasjon, hvor informasjonen ikke får plass på et tabellformat. Du kan bruke parametret -property til å angi hvilke egenskaper du vil ha med.

Slik :

image

Hvis du lurer på hvilke egenskaper du har tilgjengelig – husk get-member.

image

Format-Table

Med Format-Table kan vi sette opp tabeller, hvor hvert objekt listes på en linje i tabelloppsett. En kommando som get-wmiobject kjører resultatet som standard ut som liste. La oss se på hvordan vi kan formatere resultatet fra get-wmiobject med format-table:

 image

På lik linje med Format-List kan vi også her angi hvilke egenskaper vi ønsker å ha med. Til dette bruker vi –property (kommandoen under skrives som en linje):

image

Som du ser av resultatet er alle kolonnene like store. For å unngå dette kan du bruke parameteret –autosize (fortsatt en linje)

image

Format-Wide

Det finnes også en formatering for å kjøre ut resultatet i to eller flere kolonner. Denne heter Format-Wide, og er tilpasset der vi skal dumpe ut en egenskap, og ønsker å kjøre resultatet over flere kolonner, slik at vi slipper å scrolle så mye.

image

Du kan også formatere antall kolonner slik du selv vil:

get-service | format-wide displayname -column 3

Format-Custom

Vi kommer ikke til å opprette egne formateringer her, men det finnes altså en mulighet til det. Da dette krever en god del kjennskap til .NET og XML, går vi ikke igjennom det her. Det betyr i praksis at man definerer en XML fil med formateringen, og benytter cmdlet’en Update-FormatData for å registrere formateringen.

GroupBy

Alle Format cmdlet’ene som er beskrevet ovenfor inneholder en parameter med navn GroupBy. Denne lar deg samle objektene under grupperinger. Se på følgende eksempel:

Get-service | format-table –groupby status

Du ble nok litt overrasket over resultatet av denne kommandoen, da den skriver ut og grupperer fortløpende. For at du skal få det resultatet du ønsker, må du først sortere resultatet på det du ønsker å gruppere på. Det leder oss videre til sortering.

Sortering

PowerShell innehar også egne sorteringskommandoer slik at hver enkelt kommando slipper å inneholde sorteringslogikk. Dette er også en av fordelene med objektorienteringen til PowerShell, der du enkelt kan ta ut egenskaper, og sortere på dem.

La oss fortsette på eksemplet fra GroupBy:

Get-Service | sort-object status | format-table –groupby status

Sort-Object

Sort-object har også noen parametere, slik som –descending for å sortere fallende (standard er stigende) samt –unique som kun gir oss unike verdier. (som en slags select distinct for de som jobber med SQL)

La oss opprette en liste å jobbe med:

$lista =@(6,3,9,7,1,4,5,7,6,1,4,8,2,50)

MERK: Jeg oppretter lista med @ og () denne gangen. Dette må jeg ikke benytte når jeg initsierer variabelen med verdier. Men i en situasjon hvor jeg ville ha opprettet en tom liste måtte jeg benyttet det på denne måten $lista=@()

Skriv nå ut lista som den er:

$lista

Deretter sorterer du den enkelt:

$lista | sort

 

image

Sort er et alias for sort-object, og foretrekkes av mange som enklere å lese.

Prøv nå:

$lista | sort –unique

Kommandolinja over sortere stigende, og tok bare med en av hver verdi. Hvis du ønsker å ha den største verdien øverst, og sortere fallende kan du benytte –descending

$lista | sort –unique -descending
image 

Merk! Det finnes også en cmdlet Get-Unique som lister opp unike verdier uten å sortere.

Men, hva om sorteringen din ikke fungerer som forventet?

La oss ta et eksempel – denne gangen med en hashtabell:

$hashlista =@{a=6;b=3;c=9;d=7;e=1;f=4;g=5;h=7;i=6;j=1;k=4;l=8}

Deretter så prøver vi å sortere denne lista:

$hashlista | sort

image

Resultatet blir ikke som forventet – uansett hvordan du prøver å sortere en hashliste, blir resultatet det samme. Årsaken til dette er at hashtabellen ikke sender objektene ut på ”pipen”, altså til neste kommando slik vi har blitt vant til. Hashtabellen sender kun seg selv, ikke innholdet. Dette ser du også om du prøver å konvertere den til kommaseparert fil eller gjøre utføre andre funksjoner på innholdet i hashtabellen.

Hvordan går vi frem for å sortere denne da?

Hvis vi tar en titt på hashtabellens egenskaper og metoder, vil vi se den inneholder metoden GetEnumerator. Ta en titt selv:

$hashlista | get-member

Hvis vi ønsker å sortere en hashtabell ( eller ønsker å ha hver enkelt forekomst i hashtabellen av andre årsaker) kan vi kalle denne metoden.

$hashlista.GetEnumerator() | sort -property Value

image

Denne gangen ser du at sorteringen ble korrekt.

Out-Gridview

Nytt i Powershell 2.0 er også Out-GridView. Denne krever .NET Framework 3.5 installert, og er kjekk for å enkelt manipulere utdata på en oversiktlig måte.

Med Out-GridView kan du i ett grafisk grensesnitt sortere og filtrere på informasjonen, slik at den er enklere å navigere seg frem i.

Eksempel på bruk av Out-GridView.

Get-Process | Out-Gridview
image
Where-Object

Where-object lar oss filtrere eller begrense hvilke av objektene fra resultatet vi vil ha med. Det betyr at vi tar resultatet av en cmdlet og piper inn i Where-Object for filtrering. Where-Object består av en kodeblokk, og må derfor ledsages av en { foran og en } til slutt. Her er et eksempel sammen med get-wmiobject cmdlet:

Get-wmiobject –class win32_service | where {$_.state –eq “Stopped”}

La oss konsentrere oss om følgende del av eksempelet over: where {$_.state –eq “Stopped”}

Where er som du sikkert allerede har gjettet et alias for Where-Object. Deretter kommer ”filteret” i kodeblokken som er mellom de to { } tegnene. Vi bruker standardvariabelen $_ som gir oss ett og ett objekt fra resultatet (av kommandoen Get-WmiObject). Deretter så leser vi av egenskapen .state til objektet, og sammenligner det med verdien ”Stopped”. Dette vil altså kun gi oss en liste over de servicene som har status stopped. Du kan også her bygge på med formatering.

For eksempel (kommandoen er på en linje) :

Get-wmiobject –class win32_service | where {$_.state –eq “Stopped”} | format-wide –column 3

Her vil vi skrive ut i tre kolonner alle services med status Stopped.

I filsystemet kan vi for eksempel bruke where-object til å bare liste ut kataloger:

Get-ChildItem | where { $_.PsIsContainer} 

 

Eksport

I en del tilfeller har du behov for å formatere dataene i et annet format, slik som HTML, CSV eller XML. Dette er tilfeller PowerShell er forberedt på, og gir deg egne eksport kommandoer til formålet. Dette betyr at du eksporterer informasjonen fra PowerShell på en enkel måte, uten at hver enkelt kommando trenger å ha innebygd funksjonalitet for eksport.

La oss se på Export-CSV, Export-CliXML og ConvertTo-HTML.

Export-CSV

Når vi skal håndtere data i bulk er kommaseparerte filer noe av det mest anvendelige formatet. Det er også veldig mye benyttet da det lar oss enkelt ”massere” dataene i Excel og tilsvarende verktøy. (Selv om XML er viktig for utviklere, står CSV filer sentralt for administratorene).

La oss se på et par eksempler:

Get-Process | Export-csv prosesser.csv

I eksemplet over opprettes fila prosesser.csv, og inneholder detaljert informasjon om prosessene på maskina.

Hvis du synes det ble returnert for mye informasjon i eksemplet over, kan du ta enkelt bestemme hvilke egenskaper du skal ha med på følgende vis:

Get-process | select-object name,id,cpu | Export-Csv prosesser.csv

Du kan enkelt dumpe innholdet av ei fil til shellet med get-content.

Get-content prosesser.csv

MERK! Hvis du får feilmeldinger under kjøring av slike kommandoer, kan det være du ikke har skriverettigheter til det området du prøver å lagre fila.

Export-CSV har også et par viktige parametre:

Tabell  Parametre til Export-CSV

Parameter

Beskrivelse

-NoTypeInformation

Standardinnstillingene skriver ut ei linje øverst i fila med feltnavnene. Hvis du ikke ønsker denne linja, benytter du –NoTypeInformation

-NoClobber

Hvis du ikke ønsker å overskrive eksisterende fil, benytter du –NoClobber (som standard overskrives altså eksisterende fil)

Import-Csv

En kommaseparert fil importerer du enkelt med Import-CSV:

Import-csv prosesser.csv

Merk! Import-csv kommandoen krever at den kommaseparerte fila har en header som angir feltnavnene. Med andre ord, første linje blir tolket som angivelse av feltnavn.

La oss se på hvordan du kan importere ei kommaseparert fil, og behandle den. Til eksemplet bruker vi csv fila vi opprettet med Export-Csv over (prosesser.csv)

TestImport.ps1

$prossesser = Import-Csv prosesser.csv

foreach ($p in $prosesser)

{

    Write-host $p.Name $p.id

}

Merk følgende i eksemplet over: Ettersom at fila prosesser.csv inneholder feltinformasjon i første linje, kan vi benytte dette direkte i løkka vår. Vi går altså igjennom hver ”post” med prosesser (hver post blir lagt i variabelen $p, en i gangen, til alle er gjennomgått) Vi angir direkte feltnavnet bak punktum på variabelen $p. Dette sier noe om hvor brukervennlig Powershell er, og hvor mye den gir oss direkte i slike tilfeller.

Export-CliXML

Om du ønsker å serialisere objektene du jobber med i Powershell kan du benytte Export-CliXml og Import-CliXml. På denne måten kan du enkelt flytte eller lagre objekter over tid, og jobbe videre med dem senere.

La oss si at du ønsker å lagre prosessene som kjører på maskinen akkurat nå, slik at du kan titte nærmere på dem ved en senere anledning:

Get-process | export-clixml prosesser.xml

Dette kan du importere med Import-CliXML, men først, kjør en vanlig get-content:

Get-content prosesser.xml

Deretter kjører du en import med import-clixml:

Import-CliXML prosesser.xml

Export-CliXML støtter også –NoClobber for å unngå å overskrive eksisterende filer.

ConvertTo-HTML

La oss også se på hvordan vi kan eksportere resultatet til HTML med ConvertTo-HTML.

ConvertTo-HTML tar resultatet og konverterer det til HTML (slik som navnet angir), og vi benytter den sammen med Out-File for å lagre til fil. Denne har også en del muligheter, men vi starter med et enkelt eksempel:

Get-process | ConvertTo-html | out-file prosesser.html

Hvis du åpner og titter i prosesser.html vil du kan si at det ble veldig mye data der. Og det kan du faktisk enkelt påvirke i convertto-html CmdLet’en. Se på følgende eksempel:

Get-process | ConvertTo-html Name,id | out-file prosesser2.html

ConvertTo-HTML har også noen parametre som kan benyttes til å påvirke hvordan html siden skal genereres.

Parameter

Beskrivelse

Head

Setter tekst inn i <head> tag på html siden.Typisk referanser til style sheets og lignende

Title

Tekst som skal inn i <title> tag på html siden. Dette lar deg gi siden et meningsfyllt navn

Body

Denne teksten kommer i mellom <body> og </body> taggene. Lar deg angi informasjon før tabellen fra Powershell settes inn.

La oss se på et eksempel med informasjonen over:

Process2HTML.ps1

#et stylesheet med navn style.css skal være i samme katalog som denne fila
$server=hostname
$body=”Prosesser for ”+$server.toUpper()+”<hr>”
$file=”c:\”+$server+”-prosesser.html”
# * teksten under er på en linje *
Get-process | ConvertTo-HTML Name,Id,WorkingSet,CPU –Title “Prosessrapport.” –Head “<link rel=stylesheet type=text/css href=style.css>” –Body $body | out-file $file 

Vi har nå tittet på enkel formatering, gruppering, sortering – håper du har nytte av denne guiden 🙂

Guide/Powershell

Kom igang med Powershell – del 4 – Utvikle script i PowerShell

Posted by ragnar harper on

Utvikle script i PowerShell

Dette er del 4 av Kom igang med Powershell guiden min.

Del 1: Kom igang med Powershell

Del 2: Kom igang med Powershell

Del 3: Kom igang med Powershell

Frem til nå har vi sett på hvordan kommandolinjen fungerer i PowerShell . Vi skal nå se på nyttige mekanismer for å kunne skrive script i Powershell. I denne sammenheng skal vi blant annet ta en titt på variabler, objekter, operatører, løkker og valg.

Grunnleggende om script

Script er et sett med kommandoer satt sammen for å gjøre en jobb. Ofte samler vi operasjoner vi ønsker å gjenta i script, for slik å slippe å skrive inn alt på nytt hver gang vi ønsker å utføre jobben. For å jobbe med script trenger man i utgangspunktet ikke mer enn en editor, slik som Notepad. Jobber man mye med script kan det være man ønsker å investere i noe som har litt mer funksjoner, blant annet Intellisense (som foreslår fullførelse av det du skriver). Det finnes flere editorer du kan benytte, slik som Sapien Primalscript , PowerGUI Editor og Powershell ISE, bare bruk det som funker for deg. Jobber man mye med script bør man også tenke på hvordan man skal håndtere ulike versjoner av script. Til dette kan man benytte alt fra Sharepoint document librarys , CVS, TeamServer og Sourcesafe. En del av editorene har muligheter til å direkte jobbe mot disse kildene.

En helt enkel malfil kan se slik ut :

#=====================================================================
#
# NAME: Scriptets navn
#
# AUTHOR: Ragnar Harper
# CREATED DATE : 02.05.2007
#
# DESCRIPTION: Beskriv formål med scriptet
#
# HISTORY: Endringer noteres her
#
#=====================================================================

Etter Name: legger jeg scriptets navn. I tillegg legger jeg inn en beskrivelse av scriptet under Description , og en oppdateringslogg under History.

Selv om man husker hvorfor man lager scriptet når man utvikler det, kan det ofte være vanskeligere å huske det etter ett år..

Bruk av variabler

Variabler identifiseres i PowerShell med $. Det betyr at alle variabler begynner med ett dollartegn. Vi skal i dette avsnittet se litt på bruken av variabler.

Benytt din favoritt editor til å skrive inn følgende linjer, som lagres som Script1.ps1:

$fornavn = Read-Host"Tast inn Fornavn"
$etternavn = Read-Host "Tast inn Etternavn"
Write-Host "Du heter $fornavn $etternavn"

I dette eksemplet oppretter vi to variabler, en navngitt $fornavn og en navngitt $etternavn. Vi benytter kommandoen Read-Host til å lese inn verdier i variabelene. Inntastingen av verdi avsluttes med at brukeren trykker <ENTER>.

Åpne PowerShell (hvis du ikke allerede har det åpent) og gå til mappen hvor du lagret script1.ps1

Start scriptet med å kjøre .\Script1.ps1

Du får da en dialog som ser noenlunde ut som denne:

image

Legg merke til at Read-Host autmatisk legger til : (kolon) bak teksten vår.

La oss gå videre, og lage scriptet Script2.ps1 :

$tallA = Read-Host("Tast inn tall 1")
$tallB = Read-Host("Tast inn tall 2")
Write-Host "Sum=$tallA+$tallB"

Lagre, og kjør scriptet. Hvordan ble resultatet denne gangen? Ble det som forventet?

La oss prøve oss på en endring av kildekoden. Endre linjen med Write-Host til å lyde som følger:

$tallA = Read-Host("Tast inn tall 1")
$tallB = Read-Host("Tast inn tall 2")
Write-Host (“Sum=” + ($tallA + $tallB))

Lagre Script2.ps1, og prøv å kjøre det en gang til. Ble resultatet annerledes nå?

Hos meg ble det slik:

image

Og dette skyldes at tallene håndteres som en tekststreng, og ikke som tall. Så hvordan kan vi fortelle PowerShell at vi jobber med tall?

I PowerShell kan vi eksplisitt angi hvilken datatype vi jobber med. Vi har frem til nå ikke hatt behov for det, og det er fordi PowerShell er veldig dyktig til å avgjøre hvilken datatype du ønsker å jobbe med. Men i enkelte tilfeller kan det være nødvendig å angi hva vi ønsker å ha. I Tabellen under ser du ulike datatyper du kan angi, men først et eksempel:

[int]$Tall1=Read-Host(“Tast inn tall 1”)
[int]$Tall2=Read-Host(“Tast inn tall 2”)
$tall1+$tall2

Når du kjører dette eksemplet, prøv også å lese inn bokstaver eller setninger. Som du ser feiler PowerShell da, med beskjed om at den ikke kan lagre verdien i en Integer. Du må altså oppgi et heltall for å få Powershell til å godta verdien.

La oss se på et annet eksempel også:

$x=”2”
$y=2
$x+$y
$y+$x

Hva skjer her? Jo, eksemplet viser at du kan sette de verdiene du vil til en variabel, og når du knytter dem sammen, slik som gjennom $x+$y og $y+$x så benytter Powershell datatypen til variabelen lengst til venstre for å avgjøre datatypen. I eksemplet $x+$y er $x en tekststreng (string), og svaret blir derfor to tekststrenger som blir satt sammen. I eksemplet $y+$x er $y et heltall, og Powershell prøver derfor automatisk å konvertere $x til heltall etter beste evne. Ettersom at tekststrengen ”2” kan oversettes til heltallet 2, utfører den operasjonen, men denne gangen altså med heltall verdier.

Tabell 2 Eksempel på typer og deres alias i PowerShell

PowerShell alias

Tilsvarende .NET type

[int]

System.Int32

[long]

System.Int64

[string]

System.String

[char]

System.Char

[bool]

System.Boolean

[byte]

System.Byte

[double]

System.Double

[decimal]

System.Decimal

[float]

System.Single

[single]

System.Single

[regex]

System.Text.RegularExpressions.Regex

[array]

System.Array

[xml]

System.Xml.XmlDocument

[scriptblock]

System.Management.Automation.ScriptBlock

[switch]

System.Management.Automation.SwitchParameter

[hashtable]

System.Collections.HashTable

[psobject]

System.Management.Automation.PSObject

[type]

System.Type

På mange av disse datatypene finnes datatypen som et array ( en samling med verdier ). Dette kan vi angi med [] etter datatypenavnet. Eksempel for int og long : [int[]] [long[]]

La oss si at vi ønsker å initisere variabelen $x som en samling med tallene 1.0, 2.2, 3.3 ,4.4, 5.5. Vi ønsker å lagre tallene som datatypen [double], en datatype som lar oss lagre desimaltall.

$x=1.0,2.2,3.3,4.4,5.5
$x.GetType()

Resultatet av denne operasjonen vil være et array – men av typen Object. Dette får du sjekket med komjmandoen $x.GetType(), som gir følgende utdata:

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array

Hvorfor er dette et problem tenker du kanskje nå? Object funker bra i mange tilfeller, men kan gi feil senere. La oss se på følgende eksempel:

image

Resultatet ble riktig. Dette viser hvor kraftfullt PowerShell er til å ville gjøre det riktig for oss. Men, når datasamlingen vår er av type Object, betyr det at vi kan få den til å feile ganske enkelt, ved at de ulike verdiene kan være av forskjellige datatyper.

Merk! For sikkerhetsskyld bør du nullstille $sum variabelen på følgende måte:

$sum=””

Slik tester du det:

image

Denne gangen blir resultatet annerledes, og vi får ingen feilmelding. PowerShell bruker den første verdien den får inn i en variabel til å bestemme datatypen på denne variabelen. Det betyr at $sum denne gangen ble en [string] variabel, og at vi satte sammen tallene og bokstavene som om de var en tekst som skulle henge sammen.

For å sikre oss mot slike feil kan vi angi datatype og om det skal være en datasamling når vi tar i bruk variabelen.

Prøv følgende:

image

Denne gangen får du feilmelding når du prøver å sette verdien til ”R” fordi ”R” ikke er en verdi av type [double]

Du kan slette en variabel med Remove-Variable CmdLet’en. Verdier kan også slettes med Clear-Variable.

Det finnes også noen spesielle innebygde variabler. Jeg har satt disse opp i tabellen under. Det er viktig å kjenne til disse slik at du ikke benytter dem som egne variabel navn, og slik at du kan benytte dem.

Tabell 3 – Innebygde variabler

Variabelnavn

Beskrivelse

$_

Gjeldende objekt i pipeline. Dette benyttes hvor vi har behov for tilgang til hvert enkelt objekt som finnes i et resultat, enten for å sette verdier, lese verdier eller sammenligne verdier.

$^

Første tegnene (før mellomrom) i den siste linja som ble skrevet i shellet

$$

Siste tegnene (etter mellomrom) i den siste linja som ble skrevet i shellet

$?

Inneholder status på siste setning (suksess eller feil)

$args

Benyttes i funksjoner for å hente ut parametrene

$error

Hvis det oppstår feil lagres denne i $error

$home

Brukerens hjemmestasjon

$input

Inndata som pipes til en funksjon eller kodeblokk

$match

En tabell md elementene som er funnet i en –match operasjon

$ofs

Output field separator – benyttes når et array konverteres til en string. Standardverdien er mellomrom (space)

$shellid

Identifikasjonen til shellet. Benyttes til å finne ut executionpolicy og hvilke profiler som skal lastes

$stacktrace

Detaljert informasjon fra stack for siste feilmelding

Arrays

Enkelt forklart kan vi si at et array er en container for å lagre ting. For de fleste behov trenger vi kun enkle array. For administrativ skripting kan du tenke på at array er en datasamling, altså en variabel som er istand til å inneholde flere verdier. I faglitteraturen møter du også begrepet collection. For dette kursets del kan du da tenke at det er et array. Dere får ha meg unnskyldt for at jeg i teksten benytter begrepet datasamling / array om hverandre. Da de fleste administratorer har liten erfaring med skripting og programmering, prøver jeg å gjøre det så forståelig som mulig.

La oss lage et enkelt array:

image

Vi kan aksessere hver enkelt verdi i et array gjennom å angi indeksen til verdien vi ønsker. I eksempelet over med $arr har vi 10 verdier. Disse aksesseres gjennom en indeks som starter på 0, og teller opp til så mange elementer som vi har. I dette tilfellet aksesseres altså hver verdi ved å angi indeks fra 0 til 9.

image

Den siste gir deg ingen verdi, da det kun ligger verdier fra 0 til 9.

Forøvrig kunne vi skrevet initiseringen av $arr på en annen, og mer effektiv måte:

image

La oss se på et mer praktisk rettet eksempel hvor vi ønsker å hente ut informasjon fra flere maskiner. Maskinene vi skal hente ut informasjon om ligger i fila server.txt. Server.txt fila er formatert med et servernavn på hver linje, slik som dette:

ServerA
ServerB
ServerC


Tips

! Lag din egen liste over servere i ditt eget nettverk.

La oss lese inn innholdet av fila til en variabel med navn $serverliste:

image

Jeg har benyttet en punktum til å angi maskinen jeg kjører på, de andre maskinene har jeg angitt med navn,

La oss gå igjennom hver server (hver linje, eller hvert element i array’et om du vil)

image

Om en av serverne ikke er tilgjenglig, eller begrenset med brannmur får du følgende melding:

image

Vi ser at serveren hyper1.harper.labs ikke var tilgjengelig under kjøring av koden.

Vi har allerede under kurset benyttet arrays og vi kommer til å benytte det flere ganger.

En annen type array er et hash array, også kalt for dictionaries og associative arrays.

Dette er array hvor hvert element består av en nøkkel og en verdi. Vi kan da benytte nøkkelen til å gjøre oppslag, istedet for indeks nummeret slik vi må på vanlige array. La oss ta eksemplet hvor vi trenger å lagre salgstall for tre avdelinger:

Avdeling Salgstall

Trondheim 200 000

Oslo 100 000

Bodø 150 000

Vi kan nå deklarere dette i PowerShell på følgende måte:

$salgstall = @{“Trondheim”=200000;”Oslo”=100000;”Bodø”=150000}

Vi kan nå aksesserer tallene for Trondheim og Bodø gjennom følgende kode:

$salgstall.Trondheim
$salgstall.Bodø 

image

Merk! Hvis nøkkelen inneholder blant annet mellomrom eller punktum må vi ha ” rundt ordet, slik $salgstall.”Trondheim”

Objektorientering

En av de store fordelene med PowerShell er objektorienteringen. Hva betyr så dette?

Med objektorientert mener vi at data og handlinger henger sammen. La oss se på følgende enkle eksempel:

image

”Donald Duck i store bokstaver” er en string, og man har derfor anledning til å kalle alle metoder som hører til på en string. Eksemplet viser godt hvordan data og handlinger henger sammen.

I objektorientering møter du to typer metoder som kan påkalles. (Handlinger altså) Dette er statiske metoder og instansmetoder. Instansmetoder påkalles med punktum mellom objektet og metoden. Statiske metoder påkalles med :: mellom objektet og metoden.

Eksempel på bruk av statisk metode:

image

Du kan hente ut statiske metoder fra objekttyper ved å pipe dem til get-member –static:

[string] | get-member –static

For å hente ut instansmetoder kan du kalle get-member på en instans:

“Donald Duck” | get-member

Operatører

La oss se på ulike operatører i PoweShell. Vi starter med ulike sammenligningsoperatører. Ofte har vi behov for å sjekke om en variabel har en bestemt verdi, er større enn, mindre enn, eller ikke er en bestemt verdi.

Operatør

Beskrivelse

Eksempel

Resultat

-eq –ceq –ieq

Er lik

3 –eq 3

$true

-ne –cne –ine

Er ikke lik

3 –ne 3

$false

-gt –cgt –ige

Større enn

10 –gt 7

$true

-lt –clt –ilt

Mindre enn

10 –lt 7

$false

-ge –cge –ige

Større eller lik

10 –ge 7

$true

-le –cle –ile

Mindre enn eller lik

10 –le 7

$false

-contains

-ccontains

-icontains

Samlingen på venstre side inneholder verdien på høyre side

1,2,3 –contains 2

$true

-notcontains

-cnotcontains

-inotcontains

Samlingen på venstre siden inneholder IKKE verdien på høyre side

1,2,3 –notcontains 2

$false

En annen type operatører er de som setter verdier:

Operatør

Beskrivelse

Eksempel

Tilsvarer

=

Setter variabelen til en bestemt verdi

$a = 9

 

+=

Legger til eksisterende verdi, og setter variabelen lik den nye verdien

$a+=2

$a=$a+2

-=

Trekker verdi på høyreside ifra eksisterende verdi, og setter variabelen lik den nye verdien

$a-=2

$a=$a-2

*=

Multipliserer verdi på høyreside med eksisterende verdi, og setter variabelen lik den nye verdien

$a*=2

$a=$a*2

/=

Deler verdi på høyresiden med eksisterende verdi, og setter variabelen lik den nye verdien

$a/=2

$a=$a / 2

%=

Utfører heltallsdivisjon, og gir oss rest etter utført operasjon

$a%=2

$a=$a % 2

Et særtrekk ved PowerShell jeg ønsker du skal kjenne til er at man kan sette flere verdier på en effektiv måte. Noen ganger kan du ha behov for å bytte verdi mellom to variabler, og vanligvis skriver man det slik:

$midlertidig = $a
$a=$b
$b=$midlertidig

Eksemplet bytter verdiene i $a og $b. I PowerShell kan dette skrives på følgende måte:

$a,$b = $b,$a

La oss se på et eksempel som utnytter dette på en effektiv måte. Fibonacci rekken er en populær del av matematikken . Dette er en rekke med tall, hvor hvert element er summen av de to foregående.

Fibonacci rekken: 1 1 2 3 5 8 13 21

$c=$p=1;while ($c -lt 1000) {$c;$c,$p=($c+$p),$c}

Eksemplet skriver ut Fibonacci rekken til 1000. Hvert tall som skrives ut er lik summen av de to foregående tallene i rekken. Semikolonet ( ; ) benyttes til å avslutte en setning på lik linje med linjeskift. Vi starter med å sette $c og $p lik 1. Deretter lager vi en løkke (while) som kjører så lenge c er mindre enn 1000. Deretter skriver vi ut $c, og setter $c lik ($c+$p), og vi setter $p lik c$ (altså som verdien til $c før vi legger til $p).

Dette kan du også teste på en enkel måte:

$a=$b=1 # denne linjen setter bade $a og $b til 1
$a,$b = ($a+$b),$a # setter $a lik ($a+$b) og $b settes lik $a
$a
$b

Regular Expressions

Regular expressions er “wildcards” på steroider. Det er med andre ord vesentlig mer kraftfullt en standard “wildcard”.

Regular Expressions (heretter kalt for regex) er kraftfullt, og vi skal her se på hvordan du kan komme igang med det. De operatørene som virker med regex er –match og –replace, og varianter av disse, slik som –cmatch,-imatch,-notmatch,-cnotmatch,-inotmatch, -creplace og –ireplace. C variantene står for case sensitiv, altså følsomme for store og små bokstaver, mens i variantene er ikke sensitive på store og små bokstaver.

Et godt eksempel på en problemstilling regex løser er å hente ut alle ip-adressene fra for eksempel ei logfil. Vi vet ikke nødvendigvis hvor i dokumentet ip-adressene er lagret, men vi vet hvilken form de har, og kan benytte regex til å gjenkjenne dette mønsteret, for så å hente det ut.

For å forstå regex trenger du å kjenne til noen spesialtegn som benyttes :

Tegn

Beskrivelse

\w

Tilsvarer alfanumeriske tegn eller underscore ( _ )

\d

Tilsvarer siffer (0-9)

\t

Tilsvarer TAB (tabulator)

\s

Tilsvarer mellomrom, tabulator eller newline

Ved å benytte stor bokstav istedet for liten blir meningen motsatt. Altså, \D betyr ikke siffer, og \W betyr ikke et alfanumerisk tegn eller underscore. Merk at dette ikke er et fullstendig uttrekk av spesialtegn, men de du oftest får behov for å kunne.

I tillegg til tegnidentifikatorene må du kjenne noen formateringsregler.

Format

Beskrivelse

Eksempel

Verdi

Matcher eksakt tegnene i sammenligningsverdi hvor som helst i den orginale verdien vi sammenligner med

”PowerShell” –match ”Shell”

.

Matcher et enkelt tegn

 

[verdi]

Matcher minst et av tegnene i verdi

”PowerShell” –match ”[def]”

[range]

Matcher minst et av tegnene i området som er oppgitt

 

[^]

Matcher alle tegn, bortsett fra de i klammeparentes

 

^

Matcher starten av orginal verdi

”PowerShell” –match ”^power”

$

Matcher slutten av orginal verdi

”PowerShell” –match ”ell$”

*

Matcher null eller flere forekomster av etterfølgende tegn

”PowerShell” –match ”\w*”

?

Matcher null eller en forekomster av etterfølgende tegn

 

\

Matcher etterfølgende tegn som et ”escape” tegn

 

+

Matcher repeterende forekomster av angitte mønster

 

{n}

Spesifiserer eksakt n forekomster

 

{n,}

Spesifiserer minst n forekomster

 

{n,m}

Spesifiserer minst n, men ikke mer enn m forekomster

 

Resultatet av en regex operasjon lagres automatisk i variablen $matches.

“PowerShell rules!” –match “\w* \w*”
$matches

image

Følgende eksempel krever at det er to ord for å gi true (gir false på ett ord og mer enn to):

“PowerShell rules!” –match “^\w* \w*$”

La oss benytte PowerShell til å sjekke om teksten vår er tall:

“PowerShell rules!” –match “\d”

Prøv nå følgende:

“123” –match “\d”

Det første eksemplet skal returnere false, da det ikke er et tall. I det andre eksemplet får du returnert true, ettersom at det er tall.

La oss nå sjekke om noe er en ip-adresse. VI begynner enkelt med å sjekke for 4 grupper med tall, adskilt med punktum:

"10.1.1.200" -match "^\d+\.\d+\.\d+\.\d+$" 
"10.1.1" -match "^\d+\.\d+\.\d+\.\d+$" 

image

Videre vet vi at en IP-adresse kun kan bestå at tre tall i hver gruppe. La oss erstatte + med {1.3}. Som ser av tabellen over betyr {1,3} minst en forekomst, og maks 3. Med \d{1,3} sier vi altså tall, minimum et tegn, og maksimum 3 tegn langt.

"10.1.1.200" -match "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$" 

image

La oss anvende dette i praksis med følgende eksempel.

Vi kjører kommandoen net config workstation og oppdager at linje 2 i resultatet inneholder maskinnavnet. Net config workstation er en gammel ”cmd.exe” kommando, og er ikke en PowerShell kommando som gir oss objekter å jobbe med. Vi får kun tekst i resultatet. La oss nå benytte regex til å hente ut maskinnavnet :

Først kjører vi kommandoen for å se på utdataene.

image

Deretter bestemmer vi oss for å lese ut linje nr 2. Reultatet er allerede et array med strenger for hver linje, og vi vet at alle indekser i PowerShell starter med 0. Det betyr at linje nr 2, adresseres med 1 i indeksen:

image

La oss opprette regex uttrykket vi skal sjekke mot i en variabel:

Hvis maskinen er medlem i et domene benytte du følgende uttrykk:

$expr = ‘^Full Computer.* [^.]+\.[^.]+’

Hvis maskinen ikke er medlem i et domene, benytter du følgende uttrykk:

$expr = ‘^Full Computer.* [^.]+’

Ved å benytte uttrykket vi nettopp opprettet ($expr) så trenger vi ikke å vite hvilken linje det ligger på. Vi sender inn uttrykket, og får linjen vi søker tilbake.

(net config workstation) –match $expr

image

Ved å benytte regex uttrykk kan vi unngå å måtte ”lete igjennom” en tekst for det vi ønsker å finne. En tradisjonell krevende måte å gjøre slike operasjoner på er å ”løkke” igjennom linjen, og sammenligne på leting, eventuellt så regner man seg frem til posisjon, og leser teksten basert på posisjon. Når vi jobber med variable lengder på det vi skal ha er det krevende.

En annen typisk operasjon er å finne bestemte data i en samling med ustrukturerte data. Med ustrukturert mener jeg slik som en tekst, hvor ikke all informasjon ligger i dedikerte felt, slik som for eksempel i en database.

La oss si at vi ønsker å finne IP adressen i følgende setning

Finn IP adressen min 210.12.34.19 hvis du kan

"Finn IP adressen min 210.12.34.19 hvis du kan" -match "\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}" 

Sjekk nå om hva som ligger i $matches variabelen:

$matches

Du vil da finne IP-adressen.

Løkker og valg

Et sentralt konsept innen script og programmering er løkker og valg. I mange tilfeller har vi behov for å iterere over flere verdier, gjerne også for å sammenligne verdier med en bestemt verdi for å avgjøre hva vi skal gjøre. Etterhvert som et script utføres må det ofte gjøre valg for hva det skal gjøre basert på sammenligninger.

For løkke

La oss starte med en enkel løkke som itererer over 0 til 9:

for ( $i = 0; $i -lt 10; $i+=1 ) { $i }

Formatet er slik : for (initsiering av verdi; tilstand for å utføre løkken; endring av verdi)

Vi lager oss en for løkke med følgende egenskaper:

Variabelen $i settes til 0.

Utfør løkken så lenge $i er mindre enn 10

Øk $i med 1 for hver iterasjon

Med andre ord kjøres løkken ti ganger, fra 0 til 9. Vi kunne fått den til å kjøre 11 ganger, fra 0 til 10 ved å endret –lt til –le.

La oss ta eksemplet videre og lage en multiplikasjonstabell (skriv alt på en line):

for ( $i = 1; $i -lt 10; $i+=1 ) { for ($x=1;$x -lt 10;$x+=1){ write-host `t($i*$x) -nonewline} write-host }

image

Her kjører vi to for løkker, en inne i den andre.Den ytre løkken teller fra 1 til 9. For hver av tallene som telles opp, teller den indre løkken fra 1 til 9, og vi multipliserer dermed hver av de ytre verdiene med 1 til 9. Jeg bruker også –nonewline for at tallene skal komme fortløpende på samme linje, og ikke skrives ut på hver sin linje. For formateringens skyld kjører jeg også `t foran hver, slik at det blir en tabulator mellom hvert resultat.

While løkke

En annen løkke vi har er while. Der for løkken er kjekk å bruke når du vet hvor mange ganger du skal kjøre løkken (hvor mange ganger du skal iterere), så er while løkkens fordel at den står friere i antall kjøringer. Den kan for eksempel kjøre til noe blir sant eller noe kommer til enden.

While løkken er på mange måter den enkleste å mestre, og på mange måter den mest kraftfulle.  Hver type loop har sin egen oppbygning, og While løkkens oppbygning inneholder to elementer; betingelse og kode. Som ellers bruker vi ulike typer parenteser, vanlig parenteser () for betingelse og klammeparentesene { } for koden.

I en while løkke blir betingelsene sjekket før starten av hver gjennomkjøring, og hvis betingelsen er sann, blir koden utført.

Eksempel på while løkke

$i =7
while ($i -le 85) { $i; $i +=7}

Eksemplet skriver ut syvgangen opp til 85.

Merk at kodeblokken { $i ; $i +=7 }benytter semikolon (;) for å skille kodelinjer fra hverandre. Det betyr med andre ord at kodeblokken består av to separate linjer, linje 1 med $i og linje 2 med $i+=7. Den første linjen skriver ut verdien av $i, og den andre øker $i med syv.

Do…While løkke

En Do … While løkke skiller seg fra While løkken med at betingelsen sjekkes på slutten av løkken. Dette sikrer at en Do … While løkke alltid blir utført minst en gang, da while kommer etter do

$i = 7; do { $i; $i +=7 } while ($i -le 85) 

Do … While løkken over skriver også ut syvgangen til 85.

Do Until løkke

Do .. Until løkken er en variant av Do..While løkken hvor logikken er endret.En Do..Until løkke utføres til betingelsen er sann, da avslutter den. En Do…While løkke utføres så lenge betingelsen er sann, men avslutter i det øyeblikket den ikke er sann.

$i = 7; do { $i; $i +=7 } until ($i -gt 85) 
Foreach løkke

Foreach løkker inneholder flere valgmuligheter enn de andre, og benyttes ofte i PowerShell.

Hovedfunksjonaliteten i en foreach løkke er at den gjennomgår alle elementene i et array (collection, eller samling med flere verdier om du vil). Legg spesielt merke til bruken av ordet in.

Foreach($element in $collection) { utfør dette }

Syvgangen i en foreach løkke presenteres på følgende måte:

foreach ($number in 1,2,3,4,5,6,7,8,9,10,11,12 ) { $number * 7}

En annen måte å skrive dette på (vi snakker jo tross alt PowerShell) er som følger:

$arr=1..12
foreach($number in $arr){ $number *7 }

For å vise hvor kompakt dette kan skrives i PowerShell – se på dette eksempelet:

$o = 1..12 |% {$_ * 7 }
$o

Merk! % er et alias for foreach

Løkker i praksis

Her er et eksempel på løkke i pipeline. Vi henter ut alle filer med endelsen mp3, og itererer over dem. For hver fil erstatter vi mellomrom ” ” med underscore _ ,

get-childitem *.mp3 | foreach { rename-item $_ $_.Name.Replace(” “, “_”) }

Valg

Til å gjøre valg har vi to sentrale metoder, if og switch.

If sammenligner to verdier på den måten vi angir. Hvis utrykket vi sammenligner blir sant, kjøres koden i if setningen. Hvis ikke, går den videre. En if setning kan også ha en else del, som blir kjørt hvis if uttrykket blir usant.

La oss se på et enkelt eksempel:

IfDemo.ps1

[int]$i = Read-Host “Tast inn et tall”
if($i –le 10)
{
Write-host ”Mindre enn 10”
}
Elseif($i –le 50)
{
Write-host ”Mellom 10 og 50”
}
Else
{
Write-host ”Større enn 50”
}

If setninger er best egnet til å sammenligne noe med en eller veldig få verdier. Skal man sammenligne flere verdier bør man bruke switch:

[int]$var=read-host ”Tast inn et tall mellom 1 og 6”
switch ($var)
{
1 {”Option 1”}
2 {”Option 2”}
3 {”Option 3”}
4 {”Option 4”}
5 {”Option 5”}
6 {”Option 6”}
Default {“Ingen treff”}
}

Med switch har vi et sett med sammenligninger vi utfører ( i tilfellet over 1,2,3,4,5,6 – samt default som tar alle de verdiene vi ikke har tatt høyde for). Hvis uttrykket stemmer, for eksempel at vi har tastet inn 3, og vi faktisk har en sammenligning for 3, så kjøres kodeblokken som står bak 3. I dette tilfellet er det { ”Option 3” }.

Sammen med switch kan vi pgså bruke noen parametre:

Tabell 4 Switch parametre

Parameter

Beskrivelse

-regex

Gjør at tekststrengen vi sender inn blir behandlet som en regular expression string, og at vi kan benytte regex uttrykk for å sammenligne verdiene. Merk at denne ikke kan kombineres med wildcard og exact

-wildcard

Matcher strengen vi sender inn som mot alternativene vi tester mot, men med wildcard (slik at det ikke trenger å være eksakt treff)

-exact

Krever at det er et eksakt treff

-casesensitive

Standard er at den IKKE skiller mellom store og små bokstaver. Hvis du ønsker at den skal skille, må du benytte –casesensitive

-file

Tar input fra fil istedet for direkte. Hver linje i fila blir sjekket opp mot sammenligningsgrunnlaget i switch setninga.

La oss se på et eksempel med regex :

SwitchRegex.ps1

$var=”PowerShell123”,”PowerShell”,”123”,”PowerShell 123”
Switch –regex ($var)
{
“^\w+[a-zA-Z]$” { write-host $_” er et ord “}
”^\d+$” { write-host $_” er et tall ”}
”\s” { write-host $_” har et mellomrom ” }
Default { write-host ”Ingen treff for ”$_}
}

Hvis det kan være flere treff i sammenligningene, kan man påvirke om man skal fortsette å sjekke etter å ha fått et treff, eller om man skal avslutte. Dette gjøres med Break og Continue.

Dette merkes med ; Continue eller ; Break. Følgende endringer i scriptet medfører at det fortsetter:

SwitchRegexContinue.ps1

$var=”PowerShell123”,”PowerShell”,”123”,”PowerShell 123”
Switch –regex ($var)
{
“^\w+[a-zA-Z]$” { write-host $_” er et ord “; continue}
”^\d+$” { write-host $_” er et tall ” ; continue}
”\s” { write-host $_” har et mellomrom ” ; continue}
Default { write-host ”Ingen treff for ”$_}
}

Nå skal vi se hvordan switch kan benyttes sammen med –file parameteren til å finne alle linjer med ei IP-adresse i teksten.

Opprett fila adresser.txt med følgende innhold:

Dette er ei linje med ip 12.19.54.123
På denne linja har jeg 76.3.122.19
Denne linja har ingen IP
og denne linja har 10.10.10.10
Denne linja derimot har 201.201.233.24
Hva skal vi med alle disse linjene?

Sørg for at du har lagret fila, og kjør nå følgende kommando i PowerShell:

switch –file addresser.txt –regex {
“\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}” { $_ }
}

Resultatet skal nå se slik ut:

image

Ønsker du å kun se IP-adressene?

switch -file ustrukturert.txt -regex {
"\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}" {$_ -match "\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}" | out-null;$matches.values }
}

image

I dette eksemplet kjører vi to regular expressions – først for å hente ut de linjene som inneholder en IP-adresse, deretter en for å hente kun IP-adressen ut av disse. Jeg kjører pipe to null (out-null) for å skjule true/false som kommer ut av uttrykket ved kjøring (prøv å ta det bort –så ser du hva jeg mener).

Vi har altså hentet ut de linjene som inneholder IP-adresser. Kraftfullt, eller skal jeg heller si Powerfull?

Vi har i denne delen sett litt på variabler, datatyper, løkker og valg. I tillegg har vi sett litt på regular expressions.

Powershell/remoting

Throttling med Powershell 2.0

Posted by ragnar harper on

Ettersom at vi kan kjøre kommandoer mot flere maskiner samtidig er det nyttig å kunne kontrollere hvor mange forbindelser som opprettes på en gang. Dette styrer vi med parameteren ThrotteLimit (eller bare Throttle om du vil). ThrottleLimit setter en grense på samtidige forbindelser som opprettes. Standardverdien er 32 (som gir 32 samtidige forbindelser). Om vi setter denne til 0 er det også standardverdien som benyttes.

Om ThrotteLimit parameteren ikke settes vil den benytte opptil 32 samtidige tilkoblinger.

I eksemplene under hentes maskinnavnene fra ei fil som heter servers.txt. Dette vil være en standard tekst fil med ett servernavn per linje:

Eksempel på innhold i fila servers.txt

ServerA
ServerB
ServerC
ServerD

La oss ta følgende eksempel:

invoke-command -computer (get-content servers.txt) –scriptblock {hostname} –ThrottleLimit 10

Throttling kan også benyttes på Get-WmiObject CmdLet:

Get-WmiObject win32_Bios –computer (get-content servers.txt) –throttle 10

For å gi deg ett eksempel på hvordan dette virker som du kan teste, lager vi en liste som peker på vår egen maskin 10 ganger.

Dette gjør jeg ved å lage ett array som inneholder . (tegnet punktum) 10 ganger.

$TestListe=@($(-split (". " * 10)))

Deretter kjører vi Invoke-Command mot maskinen vår:

invoke-command -ComputerName $TestListe -ScriptBlock {hostname}

Utfallet av kommandoen hos meg er som vist i bildet under:

image

Dette er fordi vi er begrenset til å kun kjøre fem samtidige shell gjennom WS-Management som standard. Om vi ikke ønsker å endre på denne verdien kan vi benyyte ThrottleLimit til å begrense antall kall som Powershell utfører samtidig.

For eksempel som følger:

invoke-command -ComputerName $TestListe -ScriptBlock {hostname} -ThrotteLimit 4

image 

Du ser nå hvordan Powershell sender kallene, men maks 4 stykker samtidig.

Så hvorfor ønsker du å benytte ThrottleLimit?

I tilfeller hvor du ønsker å begrense antalle samtidige kall som skal kjøres benytter du ThrottleLimit. På denne måten kan du justere hvor mange forespørsler som sendes ut samtidig.

Guide/Powershell

Kom igang med Powershell – del 3

Posted by ragnar harper on

Dette er del 3 av Kom igang med Powershell guiden min.

Del 1: Kom igang med Powershell

Del 2: Kom igang med Powershell

Sikkerhetsegenskaper

Et miljø som PowerShell møter store utfordringer sikkerhetsmessig, og disse er ivaretatt på flere måter. Det er tenkt sikkerhet hele veien gjennom utviklingsløpet av PowerShell, og i nå skal vi se nærmere på disse.

Merk at denne oppgaven krever at du er administrator. Hvis du kjører Vista eller nyere, start Powershell som administrator ved å høyreklikke på Powershell ikonet og velg Run as administrator.

Problemer med scriptkjøring

Hvis du dobbeltklikker på ei fil med endingen ps1 vil du åpne Notepad, istedet for at scriptet kjøres.Faktisk vil vi også oppleve problemer hvis vi skriver inn scriptnavnet fra kommandolinjen også…

For at ikke noen skal kunne ersatte kjente programmer og cmdlets, krever PowerShell at du angir mappenavnet for å kjøre et script. Hvis du kun taster inn scriptnavnet, vil PowerShell gi deg feilmelding om at scriptet ikke finnes, som vist i figuren under.

image

For å kjøre et script i samme mappe som du står, må du legge til .\ foran scriptnavnet, som i \.scripttest.ps1.

Den andre sikkerhetstskonfigurasjonen som har påvirkning for kjøring av dine script er PowerShell Execution Policy.

Følgende fire execution policy’s er definert:

  1. Restricted standardvalget. Ingen script kan kjøres – uansett.
  2. AllSigned Alle script som er signert med en sertifikat, og hvor vi har tillit til sertifikatet kan kjøre.
  3. RemoteSigned Alle lokale script kan kjøres, også de som ikke er signert. Remote script (som lastes ned fra Outlook, Internet Explorer osv), må være signert med et sertifikat vi har tillit til for å kunne kjøre.
  4. Unrestricted Alle script kjøres, om de er signerte eller ikke.

For mer informasjon kjør kommandoen

help about_signing.

Ønsker du å se hvilken ExecutionPolicy du har, kjør følgende kommando:

Get-Executionpolicy

For å endre ExtecutionPolicy til å tillate lokale script uten signering, men krev signering fra nedlastede script, kjør følgende kommando

Set-ExecutionPolicy RemoteSigned

Bruk av digitale signaturer

Det anbefales å signere alle script, slik at du kan kjøre med en restriktiv sikkerhetspolicy i PowerShell. Vi går her igjennom en måte å signere script for bruk på utviklermaskiner. Denne fremgangsmåten gjør at du slipper å kjøpe et sertifikat for utvikling. For kjøring i bedrift anbefaler vi at man går til innkjøp av et code-signing certificate, eller utsteder et code-signing sertifikat fra egen PKI infrastruktur.

Vi kommer til å benytte verktøyet makecert.exe fra .NET Framework SDK. Dette kan lastes ned fra http://msdn.microsoft.com/netframework/downloads/updates/default.aspx . Eventuellt finnes også verktøyet i Windows Platform SDK.

Deretter kan du navigere deg til stedet hvor makecert er installert, og kjøre følgende kommando for å opprette et rotsertifikat.

.\makecert -n "CN=PowerShell Local Root" -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer -ss Root -sr localMachine

Når du kjører kommandoen vil du få et dialogvindu som spør deg om passord. Du kan angi et passord her for den private nøkkelen. For vår del  angi ett passord du husker.

Rotsertifikatet er den utstedelsesmyndigheten vi velger å ha tillit til. I tillegg til et rotsertifikat trenger vi en code-signing sertifikat som vi kan bruke på våre PowerShell script. For å utstede dette sertifikatet kjører vi følgende kommando:

 .\makecert -pe -n "CN=PowerShell Developer" -ss MY -a sha1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer

Under denne operasjonen får du også en dialogboks som spør deg om passord. Angi igjen ett passord du husker.

Disse sertifikatene skal nå ligge i maskinens certificate store. Dette kan man naturligvis sjekke via PowerShell:

dir cert:\CurrentUser\My -codesigning | fl

Du skal nå se noe som ligner på følgende:

Subject : CN=PowerShell Developer

Issuer : CN=PowerShell Local Root

Thumbprint : 5F4C985FFCC51AF1A2E0626686BFBD883177280A

FriendlyName :

NotBefore : 01.05.2007 17:26:47

NotAfter : 01.01.2040 00:59:59

Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid}

La oss nå signere et script. Først trenger vi å lage et enkelt script.

Opprett scriptet mittscript.ps1 med følgende innhold:

$navn = Read-Host("Hva heter du?")
Write-Host "Hei der..$navn"

Dette kan du for eksempel gjøre i notepad. Husk å lagre fila med etternavnet ps1. I Notepad kan du gjøre dette i Save as dialogboksen ved å legge ” ” rundt filnavnet, eller endre Save As Type til Allfiles. Lagre fila med navnet mittscript.ps1.

Forsikre deg nå om at ExecutionPolicy er AllSigned med Get-ExecutionPolicy. Hvis den ikke er AllSigned, setter du den på følgende måte:

Set-ExecutionPolicy AllSigned

Prøv å kjøre scriptet:

.\mittscript.ps1

File C:\temp\mittscript.ps1 cannot be loaded. The file C:\temp\mittscript.ps1 is not digitally signed. The script will not execute on the system. Please see "get-help about_signing" for more details..

At line:1 char:16

+ .\mittscript.ps1 <<<<

Scriptet er ennå ikke signert, og vil derfor produsere en feilmelding når du forsøker å kjøre det.

La oss signere scriptet!

Først, la oss legge codesigning sertifikatet i en variabel, deretter forsikrer vi oss om at du har fått lagt riktig sertifikat i variabelen $cert.:

 $cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]

Deretter kjører vi følgende kommando for å forsikre oss om at du har riktig innhold i variabelen $cert:

$cert

Du skal da ha ett resultat som ligner på følgende:

Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

Thumbprint Subject

———- ——-

5F4C985FFCC51AF1A2E0626686BFBD883177280A CN=PowerShell Developer

Tips: Hvis du har opprettet flere sertifikater kan det være du må endre [0] til [1] eller en annen verdi. Du kan liste ut alle mulige sertifikater ved å kjøre kommandoen

Get-ChildItem cert:\CurrentUser -codesigning

Deretter kjører vi kommandoen Set-AuthenticodeSignature kommandoen for å signere fila., som anvist i linje 31 under.

Set-AuthenticodeSignature mittscript.ps1 $cert

Prøv nå å kjøre scriptet:

.\mittscript.ps1

Du får nå opp en advarsel om at du ikke har tillit til sertifikatet som er benyttet.

image

Ved å svare A (Always) på spørsmålet (under forutsetningen at vi har tillit til oss selv), så slipper vi denne dialogboksen seinere.

Men hva skjedde med scriptet?

Ta en titt i fila mittscript.ps1. Du kan gjerne gjøre dette i PowerShell med kommandoen get-content på følgende måte:

[33] » get-content mittscript.ps1

Du vil nå finne at det er lagt til ekstra informasjon i fila. I mitt tilfelle ser denne ekstra informasjonen ut slik;

# SIG # Begin signature block

# MIIEFAYJKoZIhvcNAQcCoIIEBTCCBAECAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB

# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR

# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUmQ9ec2cWO48xOLDpsvAtUabg

# 8hOgggIqMIICJjCCAZOgAwIBAgIQh7ANpUqeMZRF/QepIQRyIDAJBgUrDgMCHQUA

# MCAxHjAcBgNVBAMTFVBvd2VyU2hlbGwgTG9jYWwgUm9vdDAeFw0wNzA1MDExNTI2

# NDdaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFBvd2VyU2hlbGwgRGV2ZWxv

# cGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCslEI1W+iqe0BTKL8TUSzD

# Uv6ZZbnUk46wzwJ9uHNggfjGEtLiVKWxvFTM1BgM+/5mYtYFz5Vssoo84VI7EuGf

# umeIU1DWyIh4J1q4Md6/Hn/NHkDQTINfCsi7+IM2BgLBk2I8KOqeweLq5F0rgcfE

# h/GmaQS6UT2hPjYyGF4vdwIDAQABo2owaDATBgNVHSUEDDAKBggrBgEFBQcDAzBR

# BgNVHQEESjBIgBBtQRksbGaKclauFeJPoqQkoSIwIDEeMBwGA1UEAxMVUG93ZXJT

# aGVsbCBMb2NhbCBSb290ghDCpdCfKLjirEFA1TvQWmFhMAkGBSsOAwIdBQADgYEA

# sO0IXieIH8Ke+t8XNH61ZJkrNXP3tClGR1Y4wErxBDdvHAw4zN3CCz2x/JjF30/h

# /SADj0keE+LVjojWg5EbSZdY3gdFu8WTBHiK0eh+g9F4XCV71SN2VYbc6wMf1BSc

# leAxAPUwzq0BDXSPbKXo2exUhK3zRZRZ7jdwqVZi0+cxggFUMIIBUAIBATA0MCAx

# HjAcBgNVBAMTFVBvd2VyU2hlbGwgTG9jYWwgUm9vdAIQh7ANpUqeMZRF/QepIQRy

# IDAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG

# 9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIB

# FTAjBgkqhkiG9w0BCQQxFgQUL8LCtPpgpJi4d7Jm+Hs2K4aBRf4wDQYJKoZIhvcN

# AQEBBQAEgYCBopCZvbkxsEh3ZUzlTQQef2UqmmHhhK5QEqLtY3VChYfCAIa4XexK

# 9/KHz9EOBcx8tk0PzqkD2Kqe3UGSYAAGf5xwTfeXGtrOyOoPCD2shKAyb7eivp++

# J4CgYwptBgoD/9P0rG1UiXFYkhWKhMUeYV0Y1KZQlPnDqaM6fjM8sw==

# SIG # End signature block

En bedre måte å lese ut informasjon på vil for de fleste være å kjøre get-authenticodesignature kommandoen :

get-authenticodesignature mittscript.ps1 | fl

Vi har nå opprettet et sertifikat vi kan bruke for test og utvikling. I produksjon anbefaler jeg at du benytter eventuell intern PKI infrastruktur eller et kjøpt code-signing sertifikat.

Etter at du har installert code-signing sertifikatet på din maskin, kan du da laste det inn, og benytte Set-AuthentiCodeSignature med det sertifikatet.

Før vi nå går videre kan det være smart å endre ExecutionPolicy tilbake til RemoteSigned

Set-ExecutionPolicy RemoteSigned

Vi har i denne artikkelen sett på signering av script i Powershell.