2026-06-18

IIS sunucu ve powershell

Kurulumunu da powershell ile tamamladığım IIS sunucuma, şu şekilde bir powershell oturumu ile uzaktan bağlıyım.

Enter-PSSession -Computername IISsunucu1

Sunucu bilgisayar üzerinde kurulu IIS sistelerini görmek için iki benzer cmdlet var:

Get-Website

ve 

Get-IISSite

İkisi de benzer çıktı üretiyor, benzer işlevselliğe sahip. Birincisi WebAdministration modülünün bir parçası. İkincisi ise IISAdministration modülünün bir parçası. İkincisinin daha yeni bir modül olduğu söyleniyor. Ama yeni modülde tüm cmdlet'lerin karşılıkları yok.

Yüksek olasılıkla sunucunuzda birden fazla IIS sitesi olacak. Bu komutlar da size bir dizi (array) nesnesi dönecek. Bu dizinin Name, ID, Physical Path, Bindings gibi alanları olacak. Genellikle bu listelenen sitelerden biri ile ilgileniyor oluruz. İstediğimiz siteyi Name alanı ile süzebiliriz.

Get-IISSite -Name site1

Nesnenin derinlerinden site loglarının saklandığı konumu çekmek için

$s1.LogFile.Directory

kullanabilirim.

Bir siteyi durdurmak veya yeniden başlatmak için

Stop-IISSite -Name site1
Start-IISSite -Name site1

kullanılabilir. Mevcut durum zaten Get-IISSite cmdlet'inin state alanında görünüyor.

Sunucumda IP tabanlı kısıtlama/izin modülü kurulumu merak ettim.

Get-WindowsFeature Web-IP-Security

şöyle bir sonuç döndü:

Display Name                                            Name                       Install State
------------                                            ----                       -------------
            [ ] IP and Domain Restrictions              Web-IP-Security                Available

Kurulu değilmiş. Kurmak için

Install-WindowsFeature Web-IP-Security

kullandım.

IIS'te IP kısıtlaması iki farklı şekilde olabilir; verilen IP adreslerine izin verip geri kalan her bağlantıyı engellemek veya tam tersi verilen IP adreslerini engellemek, geri kalan her bağlantıya izin vererek. Mevcut durumda sitemizin hangi yapıda olduğunu görelim:

(Get-WebConfigurationProperty `
-Filter "system.webServer/security/ipSecurity" `
-PSPath "IIS:\" `
-Location "site1" `
-Name allowUnlisted).Value

allowUnlisted, listede olmayanlara izin verilsin mi sorusunu yanıtlar. True dönüyorsa sitemiz listede olmayanlara izin veren, yani listedeki IP adreslerini engelleyen durumdadır. False dönüyorsa listedekilere izin verir, geri kalanı engeller. Şimdi listemizi görelim.

Get-WebConfiguration `
      -Filter "system.webServer/security/ipSecurity/add" `
      -PSPath "IIS:\" `
      -Location "site1" | Select-Object ipAddress, subnetMask, allowed

Diyelim ki IIS'in ayarı belirtilen IP adreslerini engellemek, diğer herkese izin vermek yönünde. Bunu tam tersi olarak değiştirmek için

Set-WebConfigurationProperty `
    -Filter "system.webServer/security/ipSecurity" `
    -Name "allowUnlisted" `
    -Value $false `
    -PSPath "IIS:\" `
    -Location "site1"

gibi bir ifade kullanmalıyım. 

Engellenen bir IP adresi ekleme yolu

Add-WebConfigurationProperty `
    -Filter "system.webServer/security/ipSecurity" `
    -PSPath "IIS:\" `
    -Location "site1" `
    -Name "." `
    -Value @{
        ipAddress = "192.168.1.100"
        allowed   = $false
    } 

 ya da izin verilen bir IP ekleme yolu

 Add-WebConfigurationProperty `
    -Filter "system.webServer/security/ipSecurity" `
    -PSPath "IIS:\" `
    -Location "site1" `
    -Name "." `
    -Value @{
        ipAddress = "192.168.1.101"
        allowed   = $true
    }

 

2026-06-15

Klavye vuruşları göndermek

Powershell ile bir pencereye klavye vuruşları göndermek mümkün. Bunu bir animasyon ile yapmak istedim. 3 not defteri süreci oluşturup, her birinin içine birer cümle ekleyip, sonra da bunları kapatmak istiyorum.

Açılan bir not defteri penceresinin içine bir kelime yazmak için

[System.Windows.Forms.SendKeys]::SendWait()

 kullanmam gerek. Ama bunu kullanmak için önce

Add-Type -AssemblyName System.Windows.Forms

eklemeliyim. Kapatırken de bir not defteri sürecini diğerinden ayırt etmek için pencerenin başlığına göre ayırt etmek için

[Microsoft.VisualBasic.Interaction]::AppActivate("Not Defteri")

gibi bir şey kullanmak istiyorum. Kapatırken Alt+F4 komutunun karşılığını

[System.Windows.Forms.SendKeys]::SendWait("%{F4}")

 ile göndermek, bu sorunun cevabını "Hayır" ile cevaplamak için "n" kısayolunu da

[System.Windows.Forms.SendKeys]::SendWait("n")

ile göndermek istiyorum. Her not defteri penceresinin içeriği olacak kelimeleri de aşağıdaki gibi bir değişkene koydum.

$kelimeler = "Bugun","gunlerden","pazartesi"

Hepsini tek bir betiğe koyunca:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.VisualBasic

$kelimeler = "Bugun","gunlerden","pazartesi"

$kelimeler | % {
    start notepad
    sleep -Milliseconds 500
    [System.Windows.Forms.SendKeys]::SendWait($_)
}

sleep -Milliseconds 500

try {
    $kelimeler | % {
        [Microsoft.VisualBasic.Interaction]::AppActivate("$_, Not Defteri")
        [System.Windows.Forms.SendKeys]::SendWait("%{F4}")
        sleep -Milliseconds 500
        [System.Windows.Forms.SendKeys]::SendWait("n")
        sleep -Milliseconds 500
    }
}
finally {
    ps notepad -ea silent | kill -force -ea silent
}

Kapatmak için pencere başlığına göre Alt+F4 göndermek istedim, ama Türkçe yerelleştirme dışında herhangi bir durumda AppActivate çalışmayacaktır. Bu durum için try - finally ile bütün not defteri süreçlerini sonlandırdım.

2026-06-11

Uygulama kilitlenince bildirim gelsin

Windows bir makine üzerinde çalışan bir uygulamamız var. Bu uygulama, nedendir bilinmez, bazen kilitleniyor. Böyle durumlar sonrasında yapmasını beklediğimiz işlemi yapamadığı için kesinti oluyor. Bunun önüne geçmek istiyorum.

Windows, uygulamanın bu şekilde kilitlendiği (Application hang) durumunda Uygulama olay günlüğüne 1002 kimliği ile bir kayıt düşüyor.

Logname = Application
ProviderName = Application Hang
Id = 1002

Bu olay kaydında kilitlenen uygulamanın başlatıldığı tarih ve saat bilgisi de yer alıyor. Bu bilgileri şimdilik eposta yoluyla bana atmasını istiyorum. Bu amaçla bir betik oluşturdum. Betik, son 1 dakika içinde oluşan bu tipteki bir olayları listeleyip sonuncusunu bir değişkene atıyor.

$ev1 = Get-WinEvent -FilterhashTable @{
LogName='Application';
ID=1002;
StartTime=(Get-Date).AddMinutes(-1);
ProviderName='Application Hang'
} -ErrorAction SilentlyContinue |
    Where-Object {$_.Properties[0].Value -eq "uygulama.exe"} |
    Select-Object -First 1

Olay kaydı içinde şu bilgiler var:

Uygulama adı : $_.Properties[0]

Uygulama kimliği : $ev1.Properties[2].Value 

Başlangıç zamanı : $ev1.Properties[3].Value

Kilitlenme tipi : $ev1.Properties[9].Value

Ancak başlangıç zamanı şurada yazdığım gibi, FILETIME verisi. Bunu okunabilir bir şekle getirmek için

Get-Date -Format "yyyy-MM-dd HH:mm:ss" -Date ([datetime]::FromFileTimeUtc($ev1.Properties[3].Value))

kullanıyorum. Ayrıca gelen eposta içinde bilgisayarın başlatılma zamanı da olsa iyi olur. Bu sebeple CIM içinden bu bilgiyi de çekiyorum:

Bilgisayar açılış : (gcim win32_operatingsystem).LastBootUpTime

Tarih verilerini görüntülemede yyyy-MM-dd HH:mm:ss şeklinde format görmek istediğim için bunu da dönüştürüyorum:

Get-Date -Format "yyyy-MM-dd HH:mm:ss" -Date ((gcim win32_operatingsystem).LastBootUpTime)

Olay kaydında bir de sonlanma zamanı var, Properties[4] içinde, ama bu alanda hep  4294967295 verisi var. Bu da aslında aslında henüz süreç resmi olarak sonlanmadığı için 0xFFFFFFFF değerine eşit olan

[uint32]::MaxValue

Dolayısıyla bu alanı kullanmamıza gerek yok.

Bu betiği C:\Scripts\betik1.ps1 gibi bir konuma kopyaladıktan sonra zamanlanmış görevi oluşturmak için aşağıdaki kodu kullandım.

schtasks /Create
        /TN "Uygulama Sonlanma Bildirimi"
        /SC ONEVENT
        /EC "Application"
        /MO "*[System[Provider[@Name='Application Hang'] and (EventID=1002)]]"
        /TR "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\betik1.ps1"

Böyle bir durumda eposta göndermesin, sadece uygulamayı sadece yeniden başlatılsın denebilir. Bu durumda basit bir şekilde

ps uygulama.exe | kill
start uygulama.exe

gibi içeriğe sahip bir betik iş görür. 

2026-06-02

EFI disk bölümüne sürücü harfi ataması yapmak

Şu konuyla ilgilenirken alternatif yöntemlere denk geldim, çözümün şıklığı hoşuma gitti. Öncelikle hangi disk bölümünün EFI bölümü olduğunu bulmak için

$EFIbolumu = gcim win32_volume | where SystemVolume -eq $true

Bulduğumuzdan emin olmak istersek

$EFIbolumu | ft DriveLetter, @{N="SizeMB";E={[int]($_.Capacity/1MB)}},
    @{N="FreeMB";E={[int]($_.FreeSpace/1MB)}}, 
    Label, SystemVolume, FileSystem, PageFilePresent, BootVolume

Bunun sonucunda benim durumumda şöyle bir çıktı verdi:

DriveLetter SizeMB FreeMB Label SystemVolume FileSystem PageFilePresent BootVolume
----------- ------ ------ ----- ------------ ---------- --------------- ----------
                96     45               True FAT32                False      False

EFI sürücüleri için SystemVolume = True, C: sürücüsü gibi önyükleme bölümleri için ise BootVolume = True olur. Ek ayırt edici olarak bir de PageFilePresent'i kadraja aldım, emin olmak için. Genellikle EFI bölümleri 100 MB kadar ve FAT32 yapıda olurlar.

Son aşamada Set-CimInstance alias'ı scim'i kullanıyoruz.

$EFIbolumu | where SystemVolume -eq $true | scim -Property @{DriveLetter='E:'} 

Benzer şekilde birim etiketini değiştirmek için

$EFIbolumu | where SystemVolume -eq $true | scim -Property @{Caption='EFI-part'} 

Harf atamasını geri almak için yöntem aynı:

mountvol E: /d 

---

https://devblogs.microsoft.com/powershell-community/changing-drive-letters-and-labels-via-powershell/