Powershell

# Powershell, Powershell Core

Powershell, .Net ile yazılmış başlangıç olarak Windows Management teknolojilerini hedeflemiş bir scripting dildir.

Monad, Powershellin ilk kod adıydı. Monad Manifestosu 2002 senesinde yazılmıştı ve aradan yıllar geçtikten sonra gerçek bir ürün olduğunda adı artık Powershelldi.

Powershell, Windows Management Framework (WMF) adı verilen Windowsda yönetimsel işlerinizi yaptığınız, içerisinde  araç ve Windows bileşenlerinin olduğu frameworkün parçasıdır.  Powershell yüklemek, güncellemek için aslında WMFi kurarsınız.

Powershell , Windows sistem adminlerinin en değerli aracı diyebiliriz. Bunun yanı sıra bu güzel araç bir çok amaç için kullanılabilir.

Powershelli güçlü kılan şeylerden biri de bir çok büyük teknoloji ile iletişim kurabilen araç olmasıdır. Örneğin Powershell ile AD, WMI, .NET, CMI, COM gibi bir çok teknoloji ile iletişime geçebilmesi.

Powershell kullanımı o kadar arttı ki powershell artık diğer işletim sistemlerinde de kullanılır oldu. Ama default olarak Windowsla geldiği için yaygın olduğu platform Windows.

Powershell şuanda iki ana koldan ilerliyor. Biri Windows da dahili olan Powershell, diğeri de cross platform desteği sunan Powershell Core.

Komut desteği açısından Powershell > Powershell Core diyebiliriz. Powershell de daha fazla komut bulunmaktadır.

Powershell core .net framework gerektirirken, Powershell Core, yine .netin multi platformu desteği olan .net core gerektirmektedir.

Powershell ve Powershell core u Windowsda ayrı parçalar olduğundan ayrı ayrı çalışır.

Bu yazıyı yazdığım tarih itibariyle Powershell sürümü 5.1 iken , Powershell Core kararlı sürüm numarası 6.2. Sürümden dolayı Core daha gelişmiş demek biraz yanıltıcı olacaktır.

Powershell Core daha yenilikçi ve özellikler eklenmektedir. Powershell şuan için geri uyumluluk açısından özellikle önemli. Yeni özellikler pek eklenmiyor. Genellikle bugfix ve güvenlik güncellemeleri alıyor. Belki ilerde Core default olarak kullanılır. Microsoft, powershell i daha sade yapmak için uğraştığı Core u özellikle öneriyor.

# Powershell Versions

PowerShellReleaseDefault
PowerShell 1.0November 2006Windows Server 2008 (*)
PowerShell 2.0October 2009Windows 7
Windows Server 2008 R2 (**)
PowerShell 3.0September 2012Windows 8
Windows Server 2012
PowerShell 4.0October 2013Windows 8.1
Windows Server 2012 R2
PowerShell 5.0February 2016Windows 10
PowerShell 5.1January 2017Windows 10 Anniversary Update
Windows Server 2016

Genel olarak powershell scriptlerinin powershell 3 ve üzeri uyumlu olması önemlidir. Çünkü 2yi kullanmayın diyor Microsoft. Desteği kestim diyor.

Powershell, Windows Server 2008 ile birlikte işletim sisteminin bir parçası olmuştur.

# Powershell Version

Powershell sürümümüzü aşağıdaki built-in değişkenlerden birini görüntüleyerek görebilirsiniz.

> $PSVersionTable
> $Host

# Interactive Shell

Çoğunlukla hepinizin yaptığı şey Powershell.exeyi çalıştırıp komut girmek. Evet girilen bu kabuğa verilen isim Powershell Interactive Shell.

Interactive Shell herhangi execution policyden etkilenmez.

Interactive Shellde normalde kullandığınız uygulamaları da çalıştırabilirsiniz. Örneğin notepad diyerek notepadini çağırabilirsiniz.

Otomatik komut isimlerini tamamlama özelliğine sahiptir.

Interactive shell ile yazdığınız komutları script dosyalarında, script dosyalarında yazdığınız kodu da interactive shellde çalıştırmakta bir sakınca bulunmamaktadır.

# Execution Policy

Execution Policy güvenlik amaçlı bir kontrol politikasıdır.  PS script dosyalarının çalışıp çalışamama kararını politikaya bakarak verir.

Execution Policy kullanıcıyı powershell scriptlerin çalıştırılmasına kontrol altına alabilmek için tasarlanmıştır.

Execution Policy scriptin içeriğiyle ilgilenmez. Tamamen çalışabilir mi çalışamaz mı kontrol edilir.

Powershell de  interactive olarak komutlar çalıştırıyorsanız, Powershell buna kızmaz. Sadece PS dosyalarında Execution Policy geçerlidir.

Get-ExecutionPolicy diyerek mevcut politikanızı öğrenebilir, Set-ExecutionPolicy diyerekte aşağıdaki politikalardan birini seçebilirsiniz. Aşağıdakiler en katıdan en hafife göre sıralanmıştır.

  • Restricted :
    • Komut girebilirsiniz, ancak script dosyası çalıştıramazsınız.
    • Güvenlik açısından en katı execution policydir.
  • AllSigned :
    • Script Signed ifadesini sadece güvenilir kaynaklar tarafınan bir dijital sertifikaya sahipse alır.
    • Bu politika uygulanmışsa eğer tüm bileşenleriyle scriptin Signed olması gerekir.
  • RemoteSigned :
    • Script eğer diskinizde, domain deki bir network sürücüde ise bu local bir scriptir.
    • Script internetten, email gibi güvenilir olmayan kaynaklardan indirilmişse bu script remote bir scriptir. Uygulamaların bazıları indirilen dosyalara remote flagi ekler.
    • Bu politikada Local script dosyaları çalışır.
    • Bu politikada Remote script dosyaları Trusted CAdekilerden biriyle imzalanmış ise çalışır.
    • Genellikle en çok önerilen execution policydir. Çünkü güvenilir olmayan kaynaklardan gelebilecek powershell scriptlerin çalışması önlenmektedir.
  • Default :
    • Windows 10 gibi İstemci İşletim Sistemlerinde Restricted,
    • Windows Sunucularda RemoteSigneddır.
  • Undefined :
    • Execution policy tanımlanmamış demektir.
    • Tanımlanmış Execution policyi kaldırmak için de kullanılır.
    • Tüm scopelar undefined ise policy Restricted olarak uygulanır.
  • Unrestricted :
    • İmzasız script dosyalar da çalışır, ancak kullanıcıya uyarı gösterir.
    • Windows olmayan PS Core yüklü sistemlerde tüm scopelar için default execution policydir, platform desteklemediğinden set edilip bu değer değiştirilemez.
  • Bypass :
    • Execution policy bypass edilir, kullanıcı hiç bir uyarı almaz.
    • Hiç problem yaşamasın istiyorsanız bu policy seçilebilir.
    • Güvenlik açısından en hafif kuraldır. Tüm scriptler kullanıcıya hiç bir uyarı çıkarmadan çalışır.

Execution Policynin 5 adet scopeu vardır. -Scope  parametresi ile scopeu belirtebilirsiniz.. Scopelar önem derecesine göre sıralanmıştır.  Bir script çalıştırıldığında sırasıyla bu scopedaki tanımlı ilk sıradaki scope politikası işletilir. Örneğin MachinePolicy,UserPolicy:Undefined, Process:Bypass, CurrentUser: Restricted,LocalMachine:undefined ise uygulanacak policy Bypassdır.

  • MachinePolicy
    • Group policy ile set edilebilir, Set-Execution ile değil.
    • Bilgisayardaki tüm kullanıcılara uygulanacak Group policydir.
    • Group policy ile set edilmezse undefined dır.
    • Unrestricted, RemoteSigned, AllSigned, Undefined olabilir.
  • UserPolicy
    • Group policy ile set edilebilir, Set-Execution ile değil.
    • Mevcut kullanıcıya uygulanacak Group policy dir.
    • Group policy ile set edilmezse undefined dır.
    • Unrestricted, RemoteSigned, AllSigned, Undefined olabilir.
  • Process
    • Mevcut Powershell.exe oturumuna uygulanacak policydir.
    • Process kapatıldığında policy durumu silinir. Registryde tutulmaz.
  • CurrentUser
    • Mevcut usere uygulanacak policydir. Powershelli kapatıp açtığınız da dair önceki Set edilen policy aktif olacaktır. Registryde ilgili kayıt saklanmaktadır.
  • LocalMachine
    • Powershellde Set-ExecutionPolicy dediğinizde ve Scope belirtmediğinizde varsayılan olarak yaptığınız ayar  bu scope için yapılacaktır.
    • Powershelli kapatıp açtığınız da dair önceki Set edilen policy aktif olacaktır. Çünkü registryde ilgili kayıt saklanmaktadır.
    • Windows Vista ve sonra Windows sistemlerde LocalMachine e policy set etmek için Administrator olmak gerekmektedir.
> Get-ExecutionPolicy
> Get-ExecutionPolicy -List
> Get-ExecutionPolicy -Scope CurrentUser
> Set-ExecutionPolicy -ExecutionPolicy Bypass
> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
> Set-ExecutionPolicy -ExecutionPolicy Undefined -Scope LocalMachine

# Commands

Powershellde komut tipleri:

  • Internal komutlar : Powershell içinde gelen komutlardır.
  • Functions : Powershell scripting diliyle yazılmış fonksiyon komutlarıdır.
  • External komutlar: Eski cmd.exe ile çalışabilen komutlar.

Powershell de komut isimleri verb-noun şeklindedir. Bu powershell komutlarına cmdlets (command-lets) denir.

Verbleri görmek için aşağıdaki komut kullanılabilir.

> Get-Verb

Powershell çok fazla komut içermektedir. Komutları görmek için aşağıdaki komut kullanılabilir.

> Get-Command

Parametreler – ifadesiyle girilir. Örneğin Get-Command komutu aşağıdaki gibi parametre alabilir.

> Get-Command -CommandType cmdlet

Bazı komutlar ise alias tipindedir. Yani komutu çağırmak için başka bir kısa isim verilmiştir.

Örneğin Where-Object yerine Where komutunu kullanabiliriz. Aliasları görmek için:

> Get-Command -CommandType alias

Komut keşfi için için Get-Command kullanmak faydalı olabilir.

> Get-Command -Name *process*

Powershell de parametre girerken parametreyi tamamen girmeniz gerekmeyebilir.  Örneğin aşağıdaki iki komutta aslında aynı şeydir.

> Get-Service -N defragsvc
> Get-Service -Name defragsvc

# Help

Bir komut hakkında genel bilgi edinmek için Get-Help kullanılır.

> Get-Help Get-Command
> Get-Help *service*

Help i en çok bir komutu aratmak için kullanıyoruz. Bir komutun birden fazla parametre kümesi olabilir. Detaylı görüntüleyebilirsiniz.

> Get-Help Get-Process -Full

Help dokümanlarını güncellemek için administrator yetkisi olması gerekir.

> Update-Help

Burada anlattığım konuların hakkında about sayfaları da bulunur.

> Get-Help about*

# Common parameters

Aşağıdaki parametreler powershell komutlarında ortak olarak bulunur. Ancak bu parametrelerin hepsi her komut için etkin olarak beklenen sonucu gerçekleştirmeyebilir.

  • Debug, ErrorAction, ErrorVariable, OutVariable, OutBuffer, PipelineVariable, Verbose, WarningAction, WarningVariable

Bunun yanı sıra aşağıdaki iki parametre sıklıkla bulunur.

  • Confirm, WhatIf

# Pipeline

Powershell pipeline outputu Linuxdaki bashden farklıdır. Powershellin güçlü olduğu yerdir pipeline.

Powershell de çalışan programın çıktısı  bir obje üretir ve pipeline ile bir sonraki komuta parametre olarak verilen  şey objedir, çıktının kendisi değildir.

Örneğin aşağıdaki komut ilk komutu çalıştırıp bir obje oluşturacaktır. Diğer komut ise bu objede sadece çalışan prosesleri getirecektir.

> Get-Service | Where-Object -Property Status -eq -Value Running

Powershellde pipelineda ikinci komut ilk komuttan ne alacağını hangi parametreyi alacağını bilir. Bu karar verme tekniği değere veya özelliğe göredir.

Powershell ilk olarak değere (ByValue) göre karar verir, yoksa sonra özelliğe (ByPropertyName)e bakar.

Bir komutun helpine bakıp burada hangi parametrenin pipeline hangi teknikle kabul ettiği görülebilir.

Trace ile pipeline aşamasında nasıl bir binding işlemi yapıldığını görebilirsiniz

> Trace-Command -exp { Get-Service | Stop-Service } -name parameterbinding -PSHost

# Positional Parameter

Yukarıdaki komutu aşağıdaki gibi de yazabilirdik. Parametrelerin yerine Wherein aldığı parametre alma sırasını bildiğimizden direkt yazabildik. Hatalı argüman girmiş olsaydık InvalidArgument hatası alırdık.

> Get-Service | Where Status -eq Running

Bu sebeple komutları yazarken pozisyon bazlı yazmak yerine parametre bazlı yazmak belli bir standart ve kolaylık sağlayacaktır.

# Object Member, Get-Member

Pipelinein ilettiği objelerin property, event,  method larını görmek için Get-Member i kullanabiliriz.

> Get-Service | Get-Member
 TypeName: System.ServiceProcess.ServiceController

Bu çıktıda önemli bir şey bulunuyor.  İlk çıktı bize dönen objenin tipini veriyor.

Get-Member aynı anda pipeline dan 2 obje gelmesi durumunda da bunları gösterir.

Örneğin aşağıdaki komutta hemen dizin hemde dosya objesinin üyelerini görebiliriz.

> dir > Get-Member

# Comment

Powershellde yorumlar yazmak için # işaretini kullanabiliriz.

# Bu bir yorum satiridir. 
Get-Help # yardim

Çok satırlı yorumlar oluşturmak için ise <# yorumunuz #> i kullanabiliriz.

<# Bu coklu 
yorum satiridir. 
#>
Get-Help

# Variable

Powershellde değişken tanımları $ işaretiyle başlar. Değişkenlerde aslında birer objedir.

Değişken adlarında bilinmesi gereken en önemli şeylerden biri Microsoft ürünlerinden aşina olduğumuz case-insensetivelik.

Değişken adlarının büyük küçük olması mühim değildir. Küçük olarak yazılmış bir değişken büyük harfle çağrılabilir.

> $commands = Get-Command
> $commands.Count
> $commands | Get-Members

Yukarıdaki komutta Get-Command komutunun çıktısını $commands değişkenine yazdık ve sonrasındaki komut ile de hangi özellikleri bulunduğuna baktık.

Birden çok değişkeni tek komut ile de tanımlayabiliriz.

> $a,$b,$c = 2,3,4
> $a,$b,$c = 2 # Bu şekilde kullanırsak $b ve $c null tipi yani boş değerler olarak atanır.

# Array Variable

Array değişken oluşturmak için aşağıdaki yöntemler kullanılabilir.

> $a = 1,2,3
> $b = 1..3
> $c = @(1,2,3)

Boş array oluşturup içini doldurabilirsiniz.

> $empt = @()
> $empty += 5

# Hash Table Variable

@{} ve key-value içeren yapılara Hash table denilir. Dictionary olarakta bilinirler.

> $kisi = @{ad=gokhan;soyad=kesici}
> $kisi.ad

# Automatic/Built-in Variables

Bazı değişkenler ise powershell tarafından otomatik olarak yüklenir veya built-in olarak vardır.

> Get-Variable
> dir variable:

Yukarıdaki komutlardan herhangi biriyle tanımlı built-in değişkenleri görebilirsiniz.

Bunlardan bazılarının anlamları şunlardır:

$^: Son çalışan komutu ilk parametresini alır. Yani komutun adını alır.

$$  : Son çalışan komutun son parametresini alır.  Parametre yoksa komutun kendisi ayrıca son parametredir.

> Get-Command -CommandType Alias 
> $$ #Alias
> $^# Get-Command

$? : Son çalışan komutun statüsünü (True|False) döner.

$error : Hatalar bu değişkende array de tutulur. Son alınan hata arrayin ilk elemanıdır. Error Handling için kullanılabilir.

> Get-GokhanKesici
> $?  #False
> $error[0] #Son hata

$_ veya $PSItem: Pipelinedaki Objeyi işaret eder. İkisi de benzer şeylerdir.  Örneğin aşağıdaki üç komutta aslında aynı sonucu döner.

> Get-Command | Where-Object {$_.CommandType -eq Alias}
> Get-Command | Where-Object {$PSItem.CommandType -eq Alias }
> Get-Command | Where-Object -Property CommandType -eq -Value Alias

$null : Null ojecti işaret eder. Bir çok amaç için null değişkenine ihtiyaç duyabilirsiniz.

$true : True boolean değeri için kullanılır.

$false : False boolean değeri için kullanılır.

> $a, $b, $c = $null, $true, $false

$args : Argümanları bir dizi de tutar.

> Write-Host $args.Count # test.ps1
> .\test.ps1 Merhaba Dunya #2

$PSScriptRoot : PS v3 ile birlikte gelmiştir. Scriptin çalıştığı dizini belirtir. Dosya dışında dışarıdan ps ile çağrıldığında null değerini görmeniz normaldir.

$OFS : Output Field Separator. Bir dizinin elamanları stringe dönüştürülürken ayraç olarak boşluk yerine istediğimizi kullanılabiliriz.

> $a = 1,2,3
> $OFS=-
> [string]$a # 1-2-3

# Environment Variables

Powershellde ortam değişkenleri bir PSProvider olan Env altında tutulurlar.

> Get-ChildItem Env:

Yukarıdaki komutta tüm değişkenleri listeyebilirsiniz. Buradaki herhangi bir değer ise $env:degisken_adi şeklinde ulaşabilirsiniz.

> $env:APPDATA

# Alias

Sizin için hatırlanması daha kolay isimleri komut adları yerine kullanabiliriz.

Powershellde varsayılan alias lar mevcuttur. Bunu Get-Command -Commandtype Alias ile olabileceğini görmüştük. Bunun yanı sıra custom alias larda oluşturabiliriz.

Bunun için Set-Alias komutunu kullanırız.

> Set-Alias -Name ping -Value Test-Connection

Mevcut bir aliasın ne olduğunu öğrenmek için Get-Alias kullanırız.

> Get-Alias -Name ping
> Get-Alias -Name dir
> Get-Alias -Name where
> Get-Alias -Name cd
> Get-Alias -Name foreach

Aliaslar session bazlıdır. Powershell den çıkıp girerseniz tekrar bu alias bulunmaz. Aliasları kalıcı kılmanın en basit yöntemi bu aliasları powershell $profile dosyasına yazmanızdır.

Aliaslar komut bazlıdır. Komut + parametreler şeklinde alias tanımı yapılmaz.

# Comprasion Operators

Powershell de karşılaştırma operatorleri varsayılan olarak case-insensetive karşılaştırma gerçekleştirir.  Sonuç olarak true veya false döner.

1 -eq 2
3 -gt 2
3 -gt 3
4 -lt 5
6 -lt 3
Gokhan -eq gokhan

Case-sensetive yapmak için operatorün önüne c harfini koyabilirsiniz.

Gokhan -ceq gokhan

Dilersek wildcard  ya da ? kullanarakta karşılaştırma yapabiliriz. Bunun için -like veya -notlike kullanabiliriz.

Gokhan -like *han
Gokhan -clike han
Gokhan -notlike *han
Gokhan -cnotlike G?khan

-in ve -contains operatorleriyle de içinde mi içerir mi diye sorabiliyorsunuz. Genellikle array tipi objelerin içerisinde mi içerir mi gibi sormak doğru olacaktır.  Wildcard karşılaştırma mantığıyla düşünmemek gerekir. -in parametresi powershell v3 ile birlikte gelmiştir.

gokhan -in (gokhan,kesici)
gokhan -notin (gokhan,kesici)
(gokhan,kesici) -contains kesici
(gokhan,kesici) -notcontains kesici

# Boolean Operators

Poweshellde and, or,xor ,not (!)  boolean operatörlerini kullanabiliriz.

> !$true
> -not $true
> $true -and $false
> $true -or $false
> $true -xor $false

# Arithmetic Operators

Powershellde toplam,çıkarma,bölme vs. aritmetik işlemler için arithmetic operatörler kullanılabilir.

> 2 + 2
> gokhan + kesici
> 2-3
> 6*2
> gokhan*2
> 6/2
> 6%2

# String Manupilation Operators

> gokhanksc -replace ksc,kesici
> gokhan,kesici -split ,

# Object Type Operators

-is ile obje tiplerini karşılaştırabiliriz.

> gokhan -is [string]
> 12 -isnot [string]

-as ile tip dönüşümü yapabiliriz. Alttaki ikiside tip dönüşümü yapar.

> 12 -as [string]
> [string]12

# Format Operator

String içerisinde bir komutun çıktısı,bir stringi kullanmak ve formatını düzenleyebilmek için -f format operatörünü kullanabilirsiniz.

my name is {0}, surname is {1} -f gokhan,kesici

today is {0:dddd} -f (Get-Date)

# If / Else

if (3-gt 2) {
Write-Host buyuktur
}
elseIf(3 - eq 2) {
Write-Host esit
} else {
Write-Host kucuktur}
ya da
if ( 3 -gt 2 -or 3 -eq 2 ) {
Write-Host buyuk veya esit}
else {
Write-Host kucuktur}

# ForEach

$array = (gokhan,kesici)
foreach($isim in $array){
Write-Host($isim)}
ya da 
$array = (gokhan,kesici)
$array | foreach-object {$_}
$array | foreach {$_}
$array | % {$_}
ya da
(gokhan,kesici).foreach({$_.toupper()})

# Switch

$name = gokhan kesici
switch -Wildcard ($name){
*ke* {Write-HostMatched}
default {Write-HostNot Matched}}

# while

$i = 0
while ($i -lt 3){
Write-Host $i
$i+=1}

# do while

$i = 1
do { Write-Host $i
} while ($i -lt 1)

# for

for ($i = 0; $i -lt 3; $i++){
    if ($i -eq 2) {break}
    Write-Host $i}

# Function

Powershellde iki tip fonksiyon oluşturabiliriz. Basic ve Advanced.

Basic function PS v1 ile Advanced function v2 ile sunulmuştur. Farklı olarak [CmdletBinding()]  ifadesi vardır.

Basit bir fonksiyonu aşağıdaki gibi oluşturabilirsiniz.

function EkrandaGoster {
Write-Host Merhaba Dunya
}
EkrandaGoster

Dilerseniz fonksiyona parametre almasınıda aşağıdaki gibi sağlatabilirsiniz.

function EkrandaGoster{
param($message1,$message2) # opsiyonel
Write-Host$message1$message2}
EkrandaGoster -message1 merhaba -message2 dunya
EkrandaGoster(Merhaba,Dunya) # yukarıdakiyle aynı

Sonrasında Helpini görüntüleyebiliriz.

> Get-Help EkrandaGoster

Bir diğer fonksiyon tanımlama syntaxı bir çok program dilinden aşina olduğunuz şekilde aşağıdaki gibi yapılabilir.

function EkrandaGoster($message1,$message2){
    Write-Host $message1 $message2
}
EkrandaGoster -message1 merhaba -message2 dunya
EkrandaGoster(merhaba,dunya) 

Bir pipelinedan gelen inputu kontrol etmek için begin/process/end bloklarını kullanabiliriz.

function EkrandaGoster{
    Begin {starting}
    Process {process: $_}
    End {finished} 
}
1,2,3,4 | EkrandaGoster

# Trace

Çalıştırdığınız komutun sırasıyla ne yaptığını görmek, debug etmek için Trace-Command kullanılır.

> Trace-Command -Expression { Get-Service | Get-Member} -Name * -PSHost

Örneğin yukarıda örneklerimizde kullandığımız komutun sırasıyla arkaplanda neler yaptırdığını ekrana gönderdik.

PSHost parametresi trace outputunu powershell hosta yazması içindir.

# Where-Object

Bir collection içerisinden belirttiğiniz özelliklerde arayıp onu getirmeye yarıyor.

Database mantığı ile düşünürsek bir db tablosuna collection dersek bu db tablosuna where işlemi yapmayı sağlıyor.

> Get-Process | Where-Object -Property ProcessName -eq -Value svchost

Dilersek Where-Object yerine alias olarak ? veya where ifadelerini de kullanabiliriz.

> Get-Process | Where -Property ProcessName -eq -Value svchost
> Get-Process | ? -Property ProcessName -eq -Value svchost

Bir diğer kullanım ise daha basit bir yazım şekli olan where{} şeklinde yazmak.

> Get-Process | ? { $_.processname -eq svchost }

Where i aşağıdaki gibi de kullanabiliriz.

> (Get-Process).Where( { $_.processname -eq svchost })

# Select-Object

Bir collection içerisinde bir kısım objeyi (subset object) getirmeye yarıyor.

Select-Object yerine alias olarak select kullanılabilir.

Örneğin bir collection içerisinde ilk 10 objeyi getirmeyisi isteyelim

> Get-Process | Select-Object -First 10

Yukarıdaki örnek Powershell ilk 10u buldu ve durdu. Powershell v3de bu otomatik olurken Powershell v2 de process etmeye devam ediyordu. Bu sebeple PS2 kullanacaklar -Wait parametresini de kullanabilir.

Bir diğer önemli kullanım amacı ise property seçmek. Default çıktıyı değilde istediğimiz alanların gözükmesini isteyebiliriz.

> Get-Process | Select-Object -Property ProcessName,Id

Select Object sonucunda aslında objenin bir kısmını seçmiş oluruz. Bu yüzdende obje tipi Selected olarak görülebilir

> Get-Process | Select Id | Get-Member

Dilerseniz kendiniz de yeni bir custom property oluşturabilirsiniz.

> Get-Process | Select ID,@{name=Memory;expression={$_.VM + $_.VM}}

# Select -Property vs Select -ExpandProperty

Select -Property ile bir çok property seçebilirsiniz.

Select -ExpandProperty ile bir tek property seçebilirsiniz.

Expand adından da anlaşılacağı üzere bir propertyi genişletmek açmak anlamına gelir.

Örneğin powershell.exe processin içerisindeki modülleri görmek isteyelim.

> Get-Process | ? {$_.Name -eq powershell} | Select-Object -Property Module

Yukarıdaki komut bize selected bir collection döner ancak görüntülemede sıkıntı yaşarız. Gerçekten bu collectionı detaylandırmak istersek Expand kullanabiliriz.

> Get-Process | ? {$_.Name -eq powershell} | Select-Object -ExpandProperty Module

Eğer dönülecek şey collection değilse Expand komutu header bilgini göstermeyecek ve sonucu o objenin tipinde (int,string vs.) şeklinde gösterecektir.

> Get-Process | ? {$_.Name -eq powershell} | Select-Object -Property Id
> Get-Process | ? {$_.Name -eq powershell} | Select-Object -ExpandProperty Id

-ExpandProperty için -Expand yazmakta yeterlidir.

# Sort-Object

Objeleri sıralamak için kullanılır.

Sort-Object yerine alias olarak sort kullanılabilir.

Örneğin Process leri Idye göre sıralayalım.

> Get-Process | Sort -Property Id -Descending

# Group-Object

Databasedeki group by işlemini powershellde gerçekleştirmemize olanak sağlar.

Örneğin process adlarına göre processleri gruplayabiliriz.

> Get-Process | Group -Property ProcessName

# Measure-Object

Objeleri saymak , ortalama almak, min/max bulmak için kullanabiliriz.

> Get-Command | Measure-Object 
> Get-Process | Measure-Object -Property  PM -Average -Sum -Min -Max

# Import/Export/Convert-Object

Datayı csv,html,xml,json gibi data yapılarına dönüştürebilirsiniz. Bunları export edebilirsiniz.

Örneğin aşağıdaki üç komutta sonucu csv ye dönüştürüp bunu export eder.

> Get-Process | Select name,id | ConvertTo-CSV > process.csv
> Get-Process | Select name,id | ConvertTo-CSV | Out-File process.csv
> Get-Process | Select name,id | Export-CSV process.csv

Import işlemi ise dışarıdaki bir dosyayı import , shelle getirmek  için kullanılır.

> Import-CSV process.csv

# Compare-Object

İki objeyi karşılaştırmak compare-object (diff) i kullanabiliriz.

> diff gokhan kesici

# Format-*

Powershellde komutun çıktısında bir view görürüz.

Bu view bir liste veya tablo dur.

Layout, 4 veya daha az property gösterilecekse tablo, 5 veya daha fazla property gösterilecekse liste olarak otomatik atanır.

Format-Wide yan yana sütunlara listeler oluşturmak için kullanılır.

Örneğin aşağıdaki komut prosesleri 4 kolona bölerek listelere. Property verilmezse varsayılan property olarak Name seçilir

> Get-Process | Format-Wide -Property Name -Column 4

Format-Table (ft) ise bir tablo üzerindeki formatları düzenleyebilmeyi sağlar.

> Get-Process | Format-Table -GroupBy Name

Format-List (fl), Format-Table dakine benzer ama Listeleri düzenlememizi sağlar.

> Get-WmiObject win32_logicaldisk | fl *

# Select-String

Bir text içerisinden bir stringi seçmek için kullanılır.

Linuxda sıklıkla kullanılan grep komutuna benzetebiliriz.

> echo gokhan kesici | select-string -pattern gokhan

# History

Çalıştırılan geçmiş komutları görmek için:

> Get-History

Geçmiş bir komutu  (ki bir IDye sahiptir) çalıştırmak için

> Invoke-History 15

Geçmişi temizlemek için

> Clear-History

Historydeki bir komutu aramak için bashde de benzer olan CTRL+R kombinasyonunu ya da aşağıdaki seçenekleri kullanabilirsiniz

#aranan-kelime<tab>
#aranan-id<tab>

# Launch Powershell

Powershelli çalıştırmak için alternative yöntemler:

  • File explorer üzerinde pathden powershell.exe yi çalıştırabiliriz.
  • File explorer üzerinde File menüsü altında powershelli görebilirsiniz.
  • Powershell kabuğunu açmadan Powershell komutlarını aşağıdaki gibi çağırabilirsiniz
    • > Powershell -Command Get-Process
    • > Powershell -File deneme.ps1
      

Powershell.exe kullanarak bir script i çalıştırma istediğinizde aşağıdaki seçenekleri bilmenizde fayda var. Tüm bu seçenekleri powershell.exe /? yaparakta görebilirsiniz.

  • -NoProfile: Script dosyası çalışırken profile dosyasındakilerin çalışmasını istemiyor ve sadece scriptin çalışmasını istiyorsanız bu seçeneği kullanmakta fayda var.
  • -NonInteractive: Kullanıcı ara yüzde interactive powershell ekranının çıkması önlenir.
  • -ExecutionPolicy: Mevcut powershell sessionın execution policysini yapılandırır.
  • -Version : Farklı PS versiyonları yüklü ise version belirterek çalıştırma
  • -NoExit : Program çalıştıktan sonra processden çıkma diyebiliriz.
  • -EncodedCommand : Powershellde base64 formatında encode edilmiş bir komutu çalıştırabilirsiniz.
$command = Get-Command
$byte = [System.Text.Encoding]::UniCode.GetBytes($command)
$encoded =[Convert]::ToBase64String($byte)
powershell.exe -encodedcommand $encoded -noprofile

# .NET Objects and XML

Powershell ile .NET objelerine erişip bunları kullanabiliriz.  Bunun yanı sıra powershell XML i de desteklemektedir.

> $client=New-Object System.Net.WebClient
> $content= $client.DownloadString(https://www.gokhankesici/sitemap.xml)
> $myxml = [xml] $content
> $myxml.xml

# Remote Management

Uzak makinede powershell komutları çalıştırabiliriz. Buna Powershell Remoting diyebiliriz.

Uzakta çalışan komut o bilgisayarın öz kaynaklarını kullanarak bunu gerçekleştiriyor.

Powershell komutu serialize ediliyor. Networkden çıkıyor ve hedef bilgisayara XML olarak gönderiliyor. Hedef bilgisayar deserialize işlemini gerçekleştiriyor ve komutları çalıştırıyor.

Remoting aslında xml i export edip daha sonra import etmek ile neredeyse benzer bir şey. Bunu Export/Import-CliXML komutları ile gerçekleştirip görebilirsiniz.

> Get-WmiObject win32_logicaldisk | Export-CliXML test.xml
> Import-CliXML test.xml

Remoting dediğimiz şey Powershellde Winrm servisi üzerinden gerçekleşir.

Remoting Winrm üzerinden desekte farklı servislerinde kullanılabileceğini bilmekte fayda var. Örneğin SSH üzerinden de remoting gerçekleşebilir.

Winrrm yerine neden ssh kullanılırı merak ediyorsanız. Powershell Core anlattığımız üzere çoklu platform destekliyor ve bunun için SSH servisi birebir.

Powershell aslında Winrm açısından baktığımızda bir endpointdir.

Powershell remoting in enabled olması gereklidir. Aktif olması için Winrm servisinin aktif olması gerekir.

Remoting varsayılan olarak, client işletim sistemlerinde ve 2012 öncesi Windows sunucularda disabled gelmektedir. 2012 sonrası Windows sunucularda ise aktif gelmektedir.

Powershell de aşağıdaki komut ile bu remotingi aktif edebilirsiniz. Bunun için yetki bir kullanıcı ile powershelli başlatmanız gerekmektedir.

> Enable-PSRemoting

Yukarıdaki komut Winrm servisini aktif eder. Bu komut ayrıca Winrm servisini automatic duruma getirir. 5985 portundan servis listen moda geçer ve istekleri bekler. Windows Firewallunda exceptionı kendi tanımlar.  Ve bazı endpointleri de kurar.

Endpointleri görmek için WSMAN providerı kullanılabilir. WSMAN providerdaki endpointleri listelemek için aşağıdaki komutu kullanabiliriz. Önemli bir not bu komutun çıktısındasındaki WMI ve Event Log Forwarding aslında local endpointlerdir, remote değil. Bu çıktı powershell sürümü ve işletim sürümünden sürümüne farklılık gösterebilir.

> dir WSMAN:\localhost\plugin

Özellikle WSMAN içerisinde hem client hem server için yapılandırmaları kolaylıkla listeleyebilir bununla ilgili konfigürasyonları Set-Item ile gerçekleyebilirsiniz.

> dir WSMAN:\localhost\client\defaultports\
> Set-Item WSMAN:\localhost\client\defaultports\HTTP -value 5985
> dir WSMAN:\localhost\listener\listener_xxxxx\port\

Hedef bir makine de Remotingin aktif olup olmadığını kontrol etmek için ise aşağıdaki komut kullanılabilir.

> Test-WSMan -ComputerName Testpc

Hedef bir makinenin WSMANinine bağlanmak için ise aşağıdaki komut kullanılabilir.

> Connect-WSMan -ComputerName Testpc

Diyelim ki hedef makinenin powershelline geçici bağlantı açıp komut çalıştırmak istiyoruz. Bu durumda aşağıdaki komutu kullanabiliriz.

> Set-Item WSMan:localhost\client\trustedhosts -value *
> Enter-PSSession -ComputerName 192.168.80.214 -Credential testpc\test
> Exit-PSSession

Yukarıdaki komutta önce TrustedHost umuza tüm hostlara güven dedik. Sonra ise geçici olarak bir session açtık. Artık nasıl ssh ile bir sunucuya bağlanıyorsak bunda da artık ilgili kabuğa bağlanmış olduk. Eğer source ve destination aynı domain de ise trustedhosta gerek olmayacaktı.

Eğer hata bağlanmaya çalışırken access denied hatası alıyorsanız aşağıdaki komutu çalıştırarak endpoint için gerekli yetkilendirmeleri kontrol etmeniz ve yetki vermeniz gerekebilir.

> Get-PSSessionConfiguration
> Set-PSSessionConfiguration -ShowSecurityDescriptorUI -Name Microsoft.PowerShell

Bir diğer uzak komut çalıştırma tekniği ise direkt uzak sunucuda komut çalıştırıp sonucu görmektir. Bu durumda ise Invoke-Command powershell komutunu kullanabiliriz.

> Invoke-Command -ScriptBlock { Get-Process } -ComputerName 192.168.80.214 -Credential testpc\test

Yukarıdaki komutta ComputeerName kısmına birden fazla bilgisayarı da girerek aynı anda birden fazla bilgisayarda komutun çalışmasını sağlayabilirdik. Ancak aynı anda komutu çalıştırabileceği bilgisayar sayısında defaultta bir limiti bulunuyor. -ThrottleLimit <sayi> parametresiyle aşabilirsiniz. Bu da komutu çalıştıran bilgisayarda haliyle daha fazla kaynak tüketecektir.

Enter-PSSessionın geçici session olduğunu belirtmiştir. Kalıcı sessionlar oluşturmak için New-PSSessionı kullanırız. Artık session girilebilen komutlarla birlikte gibi kullanabiliriz.

> $win10 = New-PSSession -ComputerName 192.168.80.214 -Credential testpc\test 
> Enter-PSSession -Session $win10
> Invoke-Command -ScriptBlock { Get-Process } -Session $win10

Sessionlarımızı görmek için ise aşağıdaki komutu kullanırız.

> Get-PSSession

Sessiondaki kullanıcınızı Kerberos ile ikinci kez  delage edemezsiniz. Örneğin hedef bir X sunucusunda Y sunucusuna Invoke-Command yapacak bir komut çalıştırdınız clientinizdaki kullanıcıyla, bu kullanıcıyla. Kullanıcınız varsayılan olarak delage edilmez. Domain controller da bir admin ise bunu gerçekleyebilir.

Eğer hopping işlemini yapmak istiyorsanız -CredSSP aktif edilerek Authentication CredSSP belirtilerek birden fazla hopping gerçekleştirilebilir.

# WMI, CIM 

WMI bir CIM implementasyonudur. CIM ise bir tanım standartıdır.

WMI, NT4 ile birlikte Windows sistemleri yönetmek için gelmiştir.

WMI komutları PS v1 ve Ps v2 ile birlikte ömrünü tamamlamıştır. Bu komutlar DCOM standartını baz alıyordu. CIMı değil.

WMI komutları DCOM,RPC olmasından dolayı firewall-friendly değiller.

WMI bu yazdığımız zamanda 5.1 sürümünde bulunmakta, Core sürümünde bulunmamakta. Tamamiyle kalkacağı söyleniyor.

CIM komutları PS v3 ile birlikte gelmiştir.

CIM ile WMI komutları arasındaki en belirgin fark CMI,  uzak makineye bağlanmak için WinRM servisini WSMAN protokolünü kullanır.

CIM de default olarak ne kadar WSMAN protokolü kullanıyor olsa da DCOM u dilerseniz kullanabilirsiniz.

Bu komutlar Windows platformları dışında çalışmamaktadır.

> Get-CimInstance -Class Win32_OperatingSystem 
> Get-WmiObject -Class Win32_OperatingSystem

WMI bir WQL adı verilen bir SQL syntaxında sorgu oluşturabileceğiniz bir yapıyada sahiptir.

> Get-WmiObject -Query select * from win32_computersystem

Bir instance oluşturmadan direkt classa erişim için Get-CimClass kullanılabilir. Bu komut powershell v2 de bulunmamaktadır.

> Get-WmiObject -Class Win32_OperatingSystem

# Active Directory Service Interface (ADSI)

ADSI adında da anlaşılacağı üzere AD Servisindeki namespacelere erişim sağlayabileceğim bir ara yüz.

Powershell tarafında ADSInin bir interface olarak bilinmesi yeterlidir. Yazılımcı olsaydık ADSI için COM teknolojisini bilmek gerekecekti.

> [ADSI] WinNT://./Administrator/ | Format-List *

# PSProvider, PSDrive

PSProvider powershelli diğer teknolojilere bağlayan bir adaptör görevi görür.  PSDrive ise sisteme bağlanmak için kullanılır.

Verinin tutulduğu ve powershell ile erişmek istediğimiz sisteme provider denir.

Providerlerin oluşturulma sebeplerinden biri de manage etmek için her şey için bir fonksiyon oluşturma zahmetinden kurtulmaktır. Hiyerarşik yapılar kurularak yönetiminin kolaylaştırılmasıdır.

Örneğin Registry, filesystem, Certificate data tutulan providerlardır. Sessionla yüklenen providerları, driveları görmek için:

> Get-PSProvider
> Get-PSDrive

Bu lokasyonlara erişmek isteyelim.

> Set-Location -Path C:\
> Set-Location -Path HKCU:\
> Get-ChildItem

# Out-GridView

Bu yazıyı yazdığım zaman itibariyle Out-GridView Powershell Coreda Windows için dahi bulunmuyor. Ancak Powershell Corea gelmesi istenen geleceği söylenen bir özellik.

Gridview in avantajı çıktınızı GUIde açar.

> Get-Command | Out-GridView

Örneğin yukarıdaki komutun çıktısı komutların çıktısını GUIde açıp filtremeleme vs yapabilirsiniz. Ayrıca copy paste yaparak istediğiniz yere de taşıyabilirsiniz.

# Redirect Output to File

> Get-Command 2> hata.txt 1>cikti.txt
> Get-Command | Out-File cikti.txt

# PSSnap-in, Modules

Powershell de iki tip extension bulunuyor. Snap ve Moduller.

Snapinler v1 den beri bulunmaktadır. Microsoft tarafından kullanılması pekte önerilmiyor.

Snap-inler dll olarak paketlenirler, kullanılmadan önce sisteme register edilmeleri gerekir.

Powershellde v2 ile birlikte modül desteği gelmiştir.

v2 sürümünde modüller kullanılmadan önce import edilmemelilerdi. Powershell 3 ile birlikte otomatik olarak modüllerin yüklenebilmesi özelliği gelmiştir.

Snap-inlerde autoloading i desteklemezler.

Powershellde script, binary, manifest, dynamic olmak üzere 4 çeşit modül oluşturulabilir. Biz daha çok script olanlarla ilgileneceğiz.

Modulü .psm1 uzantısıyla kaydedip sonrasında aşağıdaki gibi pathi de belirtip Import edebiliriz.

> Import-Module mymodule.psm1

Module indirmek için Powershell Gallery sayfası kullanılabilir.  PowershellGet modülü ile bu sayfadan arattıklarımızı bulabiliriz.

PowershellGet modülü Powershell 5 ile birlikte otomatik gelmektedir. Yoksa ayrıca indirip yükleyebilirsiniz.

> Install-Module -Name Get-WindowsVersion

Yüklenen modülleri ve snapinleri görmek için:

> Get-Module
> Get-PSSnap-in -Registered

Modül oluşturmak ise oldukça basittir. Yazdığımız ps1 uzantılı scripti psm1 olarak değiştirmek.  Sonrasında dilerseniz fullpath vererek dilersenizde psmodulepathdeki dizinlere atip Import edebilirsiniz.

PSModulepath ise modüllerin otomatik arandığı ve yüklendiği pathi belirtir.

> $env:psmodulepath

# Get-Content

Bir dosya içerisini okuyup bunun içerisinden istediğiniz işlemleri gerçekleştirebilirsiniz

> Get-Content -Path deneme.txt -Tail 10
> Get-Content -Path deneme.txt | where {$_ -like *gokhan*}

# Parantheses

Parantez içine girilen komutlar öncelikli / ayrı olarak çalıştırılır.

> Get-Process -ProcessName (echo conhost)

# Script block, Call Operator

Birden fazla komutu girmek gerektiği durumlarda { } script bloklarını kullanabiliriz.

Özellikle where, for, while, do gibi ifadelerle sıklıkla kullanırız. Ancak bunun dışında da kullanabiliriz.

Örneğin bir değişken tanımlayıp bu değişkenin bir çok komutun çalışmasını sağlayacak şekilde yapılandırabiliriz.

Bloğu veya bir stringi  & call operatörüyle veya Invoke-Command ile çağırabiliriz. Aksi durumda bloğun içindeki komutlar çalışmaz.

> $myvar = { echo hello; echo world }
> &$myvar
> Invoke-Command $myvar

# Subexpression Operator

Bir string içerisinde bir komutu çalıştırmak istiyor olabilirsiniz. Bu durumda $() operatörünü kullanabilirsiniz.

> Dizinler: $(dir)

# Jobs

Joblar arka planda çalışırlar. Localde job başlatmak için Start-Job komutu kullanılır.

Jobların durumunu görmek için de Get-Job diyebiliriz.

Jobı durdurmak için Stop-Job diyebiliriz.

Powershell job çıktılarını geçici olarak tutar. Çıktıyı görmek için Receive-Job kullanılır.

Jobı kaldrmak için Remove-Job kullanılır.

> Start-Job -ScriptBlock { Get-Process }
> Get-Job
> Stop-Job -Name Job3
> Recieve-Job -Name Job3
> Remove-Job -Name Job1

Wmi komutlarında -AsJob parametresi ile job oluşturulabilir. Bu parametreyi Invoke-Command ile de kullanabilirsiniz.

> Get-WmiObject -Class Win32_OperatingSystem -AsJob

# Scheduled Jobs

Scheduled job oluşturmak için bir trigger oluşturmak gerekir ve sonrasında register ekmek gerekir.

Trigger sonrası ilgili schedule job ı oluşturmak için Register işlemi gerçekleştirilir.

> $trigger = New-JobTrigger -Daily -At 5 am
> Register-ScheduledJob -Name DailyProcess -scriptblock {Get-Process} -trigger $trigger
> Get-Scheduledjob
> Unregister-Scheduledjob -Name DailyProcess

# Credentials 

Bir çok komutta -credential parametresini belirterek credential bilgisi girilebiliyor.

> Get-Help * -Parameter Credential

Credential bilginiz girildiğinde bu bilgi credential objesinde tutulur.  Bunu Crendetial parametresi gerektiren yerlerde kullanabiliriz.

> $cred = Get-Credential test
> Enter-PSSession -ComputerName 192.168.80.214 -Credential $cred

Yukarıdaki komut bize test adlı kullanıcı için bir credential objesi oluşturduk. Bize parola prompt olarak sunuldu.

Yukarıda komutla gelen ekrandan girdiğimiz parola securestring olarak tutulur. Parolayı görmek için aşağıdaki komutu gireriz. Ancak bu komut bize plaintext parolamızı vermez.

> Convertfrom-securestring $cred.password

Parolamızı plaintext olarak görmek için ise aşağıdaki komutu kullanırız.

> $cred.GetNetworkCredential() | select username,password

# Regex

Regex -match operatörüyle desteklenmektedir. Karşılaştırma için kullanılabilir.

Gokhan -match G[a-zA-Z]{4}n
Gokhan -cmatch G[a-zA-Z]{4}n
Gokhan -notmatch G[a-zA-Z]{4}n
Gokhan -cnotmatch G[a-zA-Z]{4}n

Select-string komutu regex desteklemektedir.

echo gokhan | select-string -pattern gok[a-z]an

Bir regex objesi oluşturup regex metotlarını kullanabilirsiniz.

> [regex]$rgx = gok[a-z]an
> $rgx.match(gokhan)
> $rgx.replace(gokhan,gokhan kesici)
> $rgx.split(merhabagokhandunya)

# Web

Bir siteye istek yapmak için Invoke-Webrequest kullanılabilir. İstek yapıldıktan sonra istediğimiz bilgiyi dönen cevaptan çekebiliriz

> $req = Invoke-Webrequest -uri https://www.gokhankesici.com
> $reg.Headers

# Transaction

Transaction terimini özellikle database ciler çok iyi bilir. Transaction demek bir işlem birimi manasına gelir.

Transaction en kötü , geriye dönmesi zor senaryo durumları için transaction kullanılır.

Transactiondaki mantık bir transaction içerisindeki operasyonların tamamının başarıyla tamamlanmasıyla değişikliklerin yansıtılmasıdır.

Powershell ile de komutları transaction içerisinde yönetebiliriz. Bir transaction için commit ya da roll-back gerçekleştirilebilir.

Powershelldeki transaction komutlarını görmek için:

> Get-command *transaction

Transaction kullanmak için providerın transactionı desteklemesi gerekir. Aşağıdaki komutla desteklenen providerları görebilirsiniz.

> Get-psprovider | where {$_.Capabilities -like *transactions*}

Örneğin Registry providerı transaction desteklemektedir.

Transactionı destekleyen komutları görmek için UseTransaction parametresine sahip olan komutları listelememiz gerekir.

> Get-help * -parameter UseTransaction

Bir transaction oluşturmak için Start-Transaction komutu kullanılır.

Transactioni commit etmek için Complete-Transaction , roll-back için ise Undo-transaction komutu kullanılır.

> Start-Transaction
> cd hkcu:\Software
> New-Item gokhankesici -UseTransaction
> Complete-Transaction

# Powershell Files

Powershellde dosya uzantılarının birer anlamı bulunur.

PS1 : Powershell script

PSM1: Powershell module

PSD1: Powershell module manifest

PSSC1: Powershell session configuration

PSC1: Powershell console

# Scopes

Powershellde global, local, script, private scopeları bulunmaktadır.

Örneğin Global scopedaki bir değişken, fonksiyon herhangi bir scripten dahi erişilebilir.

> $globalvar = i am global var
> function globalfun { i am global function}

# Workflow

Workflow, fonksiyonlara oldukça benzeyen bir başka teknolojidir.

fonksiyonları function, workflowları workflow anahtar kelimesiyle kullanırız.

Fonksiyonlar powershellin kendisi tarafından çalıştırılırken, workflow .Net WWF tarafından çalıştırılır.

Workflow powershelle v3 ile birlikte gelmiştir.

Workflowu fonksiyonlardan ayıran şey fonksiyonlar başlar ve biter, workflow da ise durdurulabilir, kaldığı yerden edebilir veya restart edilebilir.

Fonksiyonlar belli zamanda bir işi yapmak için, workflow ise bir işi bir çok zamanda yapabilmeye, paralelizime sahiptir.

Fonksiyonlarda komutları çalıştırırken, workflowda girilen komutlara aksiyon denilir.

Örnek bir workflow:

workflow test {
$a = 1;
$a
$a++
$a
}
test

Paralelizm için paralel anahtar kelimesi kullanır. Paralel çalışan bir yerde sıralı çalışmasını istediğiniz komutlar için sequence anahtarı kullanılabilir.

workflow paralleltest{
parallel{
test1
sequence{
test2
Get-Process
}
test3
}}
paralleltest

Dilerseniz workflowunuzu çalıştırıp durdurabilir sonra tekrar devam ettirebilirsiniz.

paraleltest -asjob
Suspend-Job Job15
Receive-Job Job15
Resume-Job Job15

Workflowda çalışan bir komut .NET WWF de çalıştığını söylemiştik. InlineScript ile birlikte Powershellde komutu çalıştırıp sonucu alabiliriz.

worfklow inlinetest {
$a = 2
inlinescript {inline1 $a}
inlinescript {inline2 $Using:a}
}
inlinetest

Yukarıdaki workflow da iki tane inline scriptde powershellde çalışır. Ancak ilk inline a değişken değerini göremez.  Çünkü farklı scopelar. Inline script kullanmak için $Using: ifadesini kullanmamız gerekir.

Bir diğer güzel özellik ise workflowda snapshot (checkpoint) alınabiliyor.

# Whatif, Confirm

Bu iki parametreye çok önem veriyorum.

Çalıştırdığınız komutun neye sebebiyet vereceğini bilmiyorsanız -whatif parametresini, onay alarak çalıştırma için ise -confirm parametresini kullanarabilirsiniz.

Bu iki parametre her komut tarafından desteklenmemektedir.

Destekleyen komutları görmek için

> Get-Help * -Parameter whatif
> Get-Help * -Parameter confirm

Örneğin :

> Get-Service | Stop-Service -whatif
> Get-Service | Stop-Service -confirm

# .NET Framework 

Powershell de .NET namespaceine erişebiliriz.

Powershelli başlattığınıda .net de ayrıca  otomatik yüklenir.

.NET güzel bir dokümantasyona sahiptir. .NET deki ilgili namespace deki class ve metotları rahatlıklar inceleyebilirsiniz.

.NET frameworküne erişimin sebebi her işi yapacak bir komutun olmaması.

Örneğin DNS sorgusu yapmak için System.NET DNS sınıfından GetHostAddresse metotunu kullanabiliriz.

> [System.Net.Dns]::GetHostAddresses(gokhankesici.com)

Dilersek bir instance objectde oluşturabiliriz.  Örneğin Security Logları çeken bir instance oluşturabilir sonrasında ilgili metotları kullanabiliriz.

> $log = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Security
> $log.clear()

Dilersekte bir databasei yine .NET aracılığıyla bağlanabiliriz. .NETde native sql ve oledb desteklenmektedir.

> $connection = New-Object -TypeName System.SqlClient.SqlConnection -Property @{ConnectionString= Data Source=myServerAddress ;InitialCatalog=mydb; User Id=myuser;Password=mypass;}
> $connection.open()

# Powershell Web Access

Powershell Remoteu browser üzerinden yapmanın en kolay yolu diyebiliriz.

Powershell ile birlikte gelmez.

Sunucularda bir özellik olarak gelir. Windows 2012 ile birlikte gelmiştir.

PWA için en az PS3, IIS, .NET 4.5 gerekir.

# Best practise

Help i ve içindeki örnekleri kesinlikle okumaya gayret gösterin.

Helpi güncel tutun

Execution policy en az RemoteSigned olsun. Group policy ile execution policyinin verildiğinden emin olun.

Her şeyi tek komutla halletmeye çalışmayın pipeline kullanın.

Collectionları çağırmak için ilk tercihiniz foreach olsun.

Cmdletlerde komutlar yoksa .Net classlarını kullanın.

İnternetten indirilen ps kodlarını iyice gözden geçirin.

Parametre olarak verilen değişkenlerde [string]$degisken şeklinde tipi belirtmekte fayda var.

Fonksiyon isimlerini Verb-Noun şeklinde vermekte fayda var.

Uzak makineye bağlanmadan önce Test-Connection ile test etmeli.

Sunucularda Powershell Remotingin aktif olduğundan emin olun.

DCOM yerine WSMAN kullanın.

# LDAP

Basit bir ldap sorgusu aşağıdaki gibi gerçekleştirilebilir.

$path = [ADSI]LDAP://dc=test,dc=local
$search = [adsisearcher]$path
$search.filter = (&objectclass=Computer)
$search.PageSize = 100000
$result = $search.FindAll()
$result.Count