one-liner etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
one-liner etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

2026-03-07

powershell muhtelif-3

Bir betiğin içinden mevcut klasörün yolunu tutan değişken

$PSScriptRoot

betiğin tam yolunu tutan değişken ise

$MyInvocation.MyCommand.Definition

Betiğin içinde çalıştığı powershell sürecinin kimlikğini görmek için (uzak oturumlarda bu, wsmprovhost'un süreç numarasını verir)

$PID

Son komut hatasız çalıştı mı sorusuna cevap (sorunun cevabı evetse True olur): 

$? 

Çalışan powershell süreci hakkında daha fazla bilgi:

[System.Diagnostics.Process]::GetCurrentProcess()

Mevcut bilgisayarın adını almak için (herhangi biri)

hostname
$env:Computername
[System.Environment]::MachineName
[System.Net.Dns]::GetHostName().Name

Oturum açmış kullanıcı adını almak için (herhangi biri)

whoami
$env:Username
[System.Environment]::UserName
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name 

 IP adresini göster (çünkü Get-NetIPAddress çok yavaş)

gcim win32_networkadapterconfiguration -filter "ipenabled = 'True'"

 

2024-12-30

Powershell muhtelif-2

Bir dosya içindeki satır sayısını bulmak için aşağıdaki iki satırdan biri kullanılabilir.

(select-string "^" dosya.txt | measure-object).count
(gc dosya.txt | measure -line).lines

Hatta bu dosyanın içinde toplam kaç harf veya kelme olduğun bulmak için

select-string "^" dosya.txt | measure-object -word -character

Ama bu yöntemler linux eşdeğeri wc'ye göre çok yavaştır. Satır sayısını bulmak için daha hızlı yöntemler:

cmd /c 'find /c /v "" dosya.txt'
[System.IO.File]::ReadLines("D:\gecici\dosya.txt").Count | measure -line 

Bir klasörün (alt klasörler hariç) boyutunu bulmak için (alt klasörleri dahil etmek için Get-ChildItem'a -Recurse eklemek gerek)

(get-childitem d:\klasor | measure-object -property length -sum).sum

Komut satırından yeni bir dosya oluşturma

ni yenidosya.txt

Klasörü içeriğiyle birlikte silme (-force gizli ve readonly dosyaları silmeden önce için onay istememesi için)

ri d:\klasor -recurse -force

Bir dosyanın boş olup olmadığını kontrol etme [1]

if ([String]::IsNullOrWhiteSpace((Get-Content D:\dosya.txt))) { "boş" } else { "boş değil" }

Bir klasördeki dosyaların içinde geçen her Nisan kelimesini Mayıs ile değiştirmek [2]

dir *.txt -recurse | % { (gc $_).replace("Nisan","Mayıs") | sc $_.fullname }

İçinde Ağustos geçen dosyaları bulmak

dir *.txt -recurse | sls "Ağustos" -list | select path

İki dizeden sadece 2.sinde geçen öğeleri listele [3]

$dize2 | ? { $dize1 -notcontains $_ }

Ya da iki dizede de olan öğeleri listele (iki kümenin kesişim kümesi)

$dize1 |? { $dize2 -contains $_ }

İki dizenin birleşim kümesini listele

$dize1 + $dize2 | select -unique

XML verisi üzerinde işlem yapmak [4]

foreach ($element in ([xml]$icerik=gc D:\veri.xml)) { $element.loc = "NBA" }

$icerik.Save("veri2.xml")

Metnin içinde HTML etiketlerini kaldır [5]

$my_string -replace '<[^>]+>',''

Dizenin en küçük, en büyük veya dizenin ortalama değerini bulmak için

($dize | measure -maximum).maximum
($dize | measure -minimum).minimum
($dize | measure -average).average

Dizedeki her bir öğenin kaç kez kullanıldığını bulmak (histogram?)

$dize | group | sort count -desc | select name,count

Her öğenin kaç kere tekrarlandığı bilgisi fazlaysa ve sadece mükerrer öğeleri görmek istiyorsak  [6]

$dize | group | ? count -gt 1 | select name

Bilgisayarın saat dilimini görmek için [7]

[System.TimeZoneInfo]::Local.StandardName

Zamanı UTC'ye çevirmek için

(Get-Date).ToUniversalTime()

Herhangi bir zaman dilimine çevirmek için (bu komut, fonksiyonun ilk parametresinin hangi zaman diliminde olduğunu bilerek çevirir)

[TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date), 'Eastern Standard Time')

Tüm zaman dilimlerini listelemek için

[TimeZoneInfo]::GetSystemTimeZones()

İşletim sisteminin ana sürümünü öğrenmek

(gcim win32_operatingsystem).caption

İşletim sisteminin kurulma tarihi (ki bu da 24H2 gibi büyük güncelleştirmeler sonrasında sıfırlanıyor)

(gcim win32_operatingsystem).InstallDate

Bir klasördeki dosyaların içinde adminstrator kelimesinin kaç kere geçtiğini bulmak:

sls administrator * | group path | sort count -desc |ft count, values -Autosize 

Mevcut işletim sistemi ne zaman açılmış (boot)?

gcim win32_operatingsystem | fl LastBootupTime

Kullanılan işlemci ile ilgili bilgi almak

gcim win32_processor | fl Manufacturer, Name, Caption, AddressWidth, DataWidth, CurrentClockSpeed, L2CacheSize, L3CacheSize, NumberOfCores, NumberOfLogicalProcessors, ThreadCount

Sırasıyla boş ve toplam RAM miktarını bulmak

gcim win32_operatingsystem | fl FreePhysicalMemory, TotalVisibleMemorySize

İşlemcinin mimarisini öğrenmek (32/64 bit) için

(gcim win32_computersystem).systemtype

Takılı diskler hakkında bilgi almak için

get-disk | fl Size, PartitionStyle, FriendlyName, LogicalSectorSize, NumberOfPartitions

Örneğin, spotify tarafından yapılan bağlantıları görmek için

Get-NetTCPConnection | where OwningProcess -in (ps svchost*).Id

Hatta şuradaki gibi IP adresini coğrafi konum ve kuruma çeviren bir yardımcı hizmet (ipwhois fonksiyonu ve iplocation) kullanarak daha işlevsel bir çıktı mümkün:

Get-NetTCPConnection | where OwningProcess -in (ps svchost*).Id | 
    select RemoteAddress, @{N="HangiKurum";E={(ipwhois $_.RemoteAddress).isp}}

Benzer powershell konuları:

---
[1] https://collectingwisdom.com/powershell-check-if-file-is-empty/
[2] https://collectingwisdom.com/powershell-replace-text-in-multiple-files/
[3] https://collectingwisdom.com/powershell-compare-two-arrays/
[4] https://collectingwisdom.com/powershell-convert-xml-to-string/
[5] https://collectingwisdom.com/powershell-remove-html-tags/
[6] https://collectingwisdom.com/powershell-find-duplicate-values-in-array/
[7] https://collectingwisdom.com/powershell-convert-date-to-utc/

2024-12-05

Bazı ilginç olay günlüğü kayıtlarına erişmek

Uzak masaüstü olay kayıtlarını görmek için

Get-WinEvent -FilterHashtable @{Logname="Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational";Id=1149}

En son kapanma ve açılma olaylarını görmek için (son 4 tanesi için, 12 başlama, 13 kapanma)

Get-WinEvent -FilterHashtable @{Logname="System";ProviderName="Microsoft-windows-Kernel-General";Id=12,13} -Max 4

En son beklenmedik şekilde sonlanan uygulamaları görmek için

Get-WinEvent -FilterHashtable @{Logname="Application";Id=1000,1002;ProviderName="Application*"} -Max 5

En son yapılan ağ bağlantılarına dair olayları görüntülemek için

Get-WinEvent -FilterHashtable @{Logname="Microsoft-Windows-NetworkProfile/Operational";Id=10000} -max 5

En son çalışan görev zamanlayıcısı olay kayıtlarına erişmek için

Get-WinEvent -FilterHashtable @{Logname="Microsoft-Windows-TaskScheduler/Operational"} -Max 4

hatta görev isimleri ile başlama olaylarını görmek için 100,129 veya 200 ID'leri süzebiliriz:

Get-WinEvent -FilterHashtable @{Logname="Microsoft-Windows-TaskScheduler/Operational";Id=100} -Max 4 |
     Format-Table TimeCreated, @{N="GorevAdi";E={$_.properties[0].Value}} -Autosize

Güç durumundaki değişiklikleri (güç adapteörünü takmak veya çıkarmak) görmek için

Get-WinEvent -FilterhashTable @{Logname="System";Id=105} -Max 6 

Arka planda başlayan ve duran hizmet olaylarına ait kayıtları görmek için

Get-WinEvent -FilterHashtable @{Logname="System";ProviderName="Service Control Manager";StartTime=(Get-Date).AddHours(-1)}

Account audit policy uygulanmamış bilgisayarlarda oturum açan kullanıcı geçmişine erişmek için

Get-WinEvent -FilterHashtable @{Logname="Microsoft-Windows-User Profile Service/Operational";Id=67} |
    Select TimeCreated, @{N="Username";E={$_.Properties[1].Value}}, @{N="LogonType";E={$_.Properties[0].Value}}

Beklenmeyen kapanmalar hakkında bilgileri görüntülemek için

Get-WinEvent -ComputerName UzakSunucu -FilterHashtable @{Logname="System";ProviderName=("*Kernel-Power","Eventlog");Id=41,6008;StartTime=(Get-Date).AddDays(-1)}

Windows Boot Id'lere erişmek için

Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='Microsoft-Windows-Kernel-Boot';Id=20} | select TimeCreated, @{N="ID";E={$_.Properties[2].Value}}

2023-10-10

Powershell ile toplu ping atma

Evet, nmap var. Ama ben bu işi Powershell ile yapmak istiyorum. Evet, firewall'ları açık olanlar cevap vermeyecek.

Hedef, mevcut yerel ağımızdaki (C sınıfı) IP adreslerine ping atarak açık olanları listelemek.

Yerel ağımızdaki IP aralığı 192.168.7.0/24 şeklinde. Son oktet 1'den başlayarak 254'e kadar değişecek.

ping işlemlerini seri olarak (biri bitmeden diğeri başlamayacak şekilde) yapmak istemiyorum. Powershell 5.1 ile paralel yapma şansım da yok. Başka ne yapabilirim? Arkaplan görevleri (background jobs)!

Tek bir hedefi pinglemek (powershell eşdeğeri Test-Connection) için arkaplan görevlerini şu şekilde kullanabilrim:

Start-Job -ScriptBlock {Test-Connection -Computername 192.168.7.1 -Count 1 -Quiet}

Bu işlemi başlattıktan sonra eğer hedef bilgisayar açıksa ve ping'lere cevap verebiliyorsa 1 saniye içinde True değeri döner. Cevap vermiyorsa 4 saniye bekler ve False döner. Ama bu işlemi 254 hedef IP adresi için yapınca işler biraz değişiyor.

1..254 | % { Start-Job {Test-Connection -Comp "192.168.7.$Using:_ -Quiet -Count 1} }

Bunun sonucunda 1'den 254'e kadar giden son oktetin her bir değeri için yeni bir powershell.exe süreci başlatılır, ve bu sürecin içinde Test-Connection çalıştırılır. Bu çok fazla bellek ve işlemci tüketen bir yöntem. Her arkaplan görevinin sadece 1 adet ICMP paketi göndermek ve almak olduğunu düşünerek bu arkaplan görevlerinin hızlıca sonlanacağını düşünüyordum, ama gördüğüm kadarıyla öyle olmuyor. Bunun sebebini bilmiyorum, ama Windows'un görev yönetimi ile ilgili bir darboğaza sebep olduğu yönünde bir izlenim oluştu. Reddit'te  gördüğüm alternatif çözüm önerisi Test-Connection cmdlet'i ile birlikte -AsJob parametresini kullanmak:

1..254 | % { Test-Connection -Comp "192.168.7.$_" -Count 1 -AsJob } |
    wait-job | Receive-Job | ? {$_.ResponseTime -ne $null} | select Address, ResponseTime

Bu komutu tek parça olarak çalıştırınca C sınıfı bir subneti taramak 4 sn sürdü. Benim aklıma böyle bir one-liner yazmak gelmezdi. Bu satırı ikiye ayırıp Wait-Job ve devamını ikinci bir satıra yazarsak Receive-Job komutunun bekleyen bütün görevleri listelemesi uzun sürüyor. Bu yöntem daha hızlı. Alias'ları kullanarak, hatta

New-Alias tc Test-connection

ile Test-Connection için de bir alias oluşturarak bu iş aşağıdaki gibi kısaltılabilir

1..254 | % { tc "192.168.7.$_" -cou 1 -asj } | wjb | rcjb | ? ResponseTime -ne $null | select Address, ResponseTime

2022-11-03

Powershell muhtelif konular

woshub.com sitesinde bulduğum birkaç güzel powershell bilgisini paylaşmak istedim.

SMB paylaşımları

Birincisi SMB sunucu ve istemcilerle uğraşmak için.

Örneğin bir dosya sunucumuz var. Bu sunucunun yapılandırma bilgilerini görmek için

PS> Get-SmbServerConfiguration

komutunu kullanabiliriz. Burada yazan parametreleri değiştirmek için, örneğin SMBv1'i kapatmak için

PS> Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force

kullanabiliriz. Paylaşılan klasörleri görmek için

PS> Get-SMBShare

paylaşımlardan birini kaldırmak için

PS> Remove-SMBShare paylasim

ve hatta paylaşımda olan açık dosyaları görmek için

PS> Get-SmbOpenFile

kullanabiliriz. Bir istemcide bağlanılmış ağ sürücüleri var mı diye bakmak için

PS> Get-SmbMapping

Yeni bir ağ sürücüsü oluşturmak için, örneğin SUNUCU üzerinde paylaşılan DOSYALAR paylaşımını Z: sürücüsü olarak bir istemciye bağlamak için

PS> New-SmbMapping -Localpath Z: -RemotePath \\SUNUCU\DOSYALAR -Username <kullanici.adi> -Password ***** -Persistent $true -SaveCredential

kullanabiliriz.

Güvenlik Duvarı

Güvenlik duvarını powershell ile yönetmek için de güzel bilgiler var. Örneğin önce hangi ağ profilinde olduğumuzu, ve bu profile göre firewall durumumuzu inceleyelim:

PS> Get-NetConnectionProfile

Burada bilgisayarımızdaki tüm ağ cihazları için (kablolu/kablosuz vs) bilgiler görüntülenir. Bunların içinden bizim hedefimiz olan ağ arayüzüne bakıp "name" alanını kaydedelim. Benim bilgisayarımda Public çıktı. Bundan sonra da firewall'da Public profiline bakalım:

PS> Get-NetFirewallProfile -Name Public

Enabled olarak True görüyorsak bu profilde güvenlik duvarımız etkindir. Değilse etkinleştirmek için

PS> Set-NetFirewallProfile -All -Enabled True

ile bütün profilleri etkinleştirebiliriz.

Varsayılan öyledir ama bir sebeple değişmişse bilgisayarımdaki gelen trafik için herhangi bir kurala uymayan paketleri engellemeyi yaplandıralım:

PS> Set-NetFirewallProfile –Name Public –DefaultInboundAction Block

Uzak masaüstü bağlantısını etkinleştirebilmek için ilgili kural grubunu etkinleştirelim:

PS> Enable-NetFirewallRule -DisplayGroup "Uzak Masaüstü"

Bu kural grubuna dahil olan kuralları görüntülemek için

PS> Get-NetFirewallRule -DisplayGroup "Uzak Masaüstü" | select Name

yazdığımda benim makinemde 3 kural geldi.

Name
----
RemoteDesktop-UserMode-In-TCP
RemoteDesktop-UserMode-In-UDP
RemoteDesktop-Shadow-In-TCP

Grubu etkinleştirdiğimizde 3'ünü de etkinleştirmiş olduk. Bu kuralların eylemleri "İzin ver". Yani bu kurallar gelen trafiğe izin vermek için yaratılıyorlar. Var olmalarının sebebi engellemek değil, izin vermek.

Varsayılan olarak güvenlik duvarı log tutmaz. Engellenen bağlantılar için log tutmayı etkinleştirmek için

PS> Set-NetFireWallProfile -Profile Domain -LogBlocked True -LogMaxSize 20000
        -LogFileName ‘%systemroot%\system32\LogFiles\Firewall\pfirewall.log’

yapabilir, yeni bir kural yaratmak için ise

PS> New-NetFirewallRule -DisplayName 'HTTP-Inbound' -Profile @('Domain', 'Private')
        -Direction Inbound -Action Allow -Protocol TCP -LocalPort @('80', '443')

gibi bir yazım kullanabiliriz.

Var olan bir kuralı değiştirmek için ise Set-NetFirewallRule kullanabiliriz. Örneğin RemoteDesktop-UserMode-In-UDP kuralını devre dışı bırakmak için

PS> Set-NetFirewallRule -Name RemoteDesktop-UserMode-In-UDP -Enabled False

yapmak yeterli. Protokole veya port numarasına göre kural aramak için Get-NetFirewallPortFilter kullanılabilir. Örneğin

PS> Get-NetFirewallRule | where {($_ | Get-NetFirewallPortFilter).LocalPort -eq 3389} | Select DisplayName

ile yerel port numarasında 3389 yazan (hem TCP hem UDP) tanımlar gelir. Ama bunlar kural mı, hayır. Kurallarla ilişkisi ne? InstanceID paramteresi ile. Get-NetFirewallPortFilter'ın döndüğü InstanceID parametresini kullanarak kurallar içinde arama yapabiliriz.

PS> Get-NetFirewallRule | where {$_.InstanceID -eq "RemoteDesktop-UserMode-In-UDP"}

Benzer şekilde 

Get-NetFirewallAddressFilter

Get-NetFirewallServiceFilter

Get-NetFirewallApplicationFilter

gibi cmdlet'ler de var.

Tekrarlanan dosyaları bulmak

Her duruma karşılaşılabilecek bir konu da tekrarlanan dosyalar. Bunları bulmak ve temizlemek için bir sürü başka program var elbet, ama powershell ile yapmak başka bir güzel. Bir hedef klasörümüz olsun; örneğin D:\dosyalar gibi. Bu klasörün altındaki diğer alt klasörlerdeki tekrarlanan dosyaları bulmaya çalışalım. Bir dosyanın başka bir dosya ile birebir aynı olduğunu anlamak için dosya özeti (file hash) hesaplamasını kullanabiliriz. Daha sonra da aynı özete sahip dosyaları süzerek sonuçları görebiliriz. Bu işin adımlarını inceleyelim. Önce D:\dosyalar klasörünün altındaki bütün dosyaları listeleyelim:

PS> Get-ChildItem -Path D:\dosyalar -Recursive

Daha sonra bütün dosyaların özetlerini hesaplayalım.

PS> Get-ChildItem -Path D:\dosyalar -Recursive | Get-FileHash

Benzersiz kopyaları değil, sadece tekrarlanan dosyaları listeleyelim. Bunun için Group-Object ile aynı özete sahip hesaplamaları gruplayıp sadece grupta 1'den fazla olan kayıtları görüntüleyelim.

PS> Get-ChildItem -Path D:\dosyalar -Recursive | Get-FileHash | Group-Object -Property hash | Where-Object {$_.count -gt 1} | Foreach-Object {$_.group | Select-Object Path, Hash}

Bu şekilde sadece tekrarlanan dosyaları listeyeleyebildik. Eğer D:\dosyalar klasöründa boyutu 50 MB'tan büyük çok sayıda dosya varsa bu yöntem uzun sürebilir, zira varsayılan SHA256 özetini hesaplamak için yoğun işlem gücü gerek. Bu konuda bir iyileştirme, önce dosya boyutunu karşılaştırıp sadece aynı boyuta sahip dosyalar için dosya özeti hesaplamaya giderek yapılabilir:

PS> Get-ChildItem -Path D:\dosyalar -Recursive | Group-Object -Property Length | Where-Object {$_.Count -gt 1} | Select-Object -Expand Group | Get-FileHash | Group-Object -Property hash | Where-Object {$_.count -gt 1} | Foreach-Object {$_.group | Select-Object Path, Hash}

Bunun sonucunda çok sayıda tekrarlayan dosya dönüyorsa bunları listenin içinden seçip tam yolunu kopyalayıp silmek zor olabilir. Onun için bu komutun çıktısını Out-GridView'a yönlendirmek, orada çoklu seçimi etkinleştirerek, seçilenleri de silmek önerilmiş. Silme işlemi için -WhatIf kullanılmış, güvenlik gereği. Gerçekten silmek için onu kaldırmak gerek. Tekrar aynı şeyi yazmayayım; yukarıdaki komutun çıktısını $tekrarlanan değişkenine atadığımızı varsayalım.

PS>  $tekrarlanan | Out-Gridview -Title "Silinecek dosyalari secin" -OutputMode Multiple | Remove-Item -Verbose -WhatIf

Sayfada -OutputMode ile -PassThru aynı anda kullanılmış; bu hataya sebep olduğu için ben çıkardım.