Windows ortamlarında lisans yönetimi, özellikle büyük ölçekli dağıtımlarda elle yapılamayacak kadar karmaşık bir hal alıyor. Yüzlerce sunucu veya iş istasyonunun lisans durumunu tek tek kontrol etmek, aktivasyon sorunlarını gidermek ya da KMS altyapısını yönetmek; doğru araçlar olmadan gerçek bir kabus olabiliyor. İşte tam bu noktada PowerShell ile slmgr.vbs kombinasyonu hayat kurtarıcı oluyor. Bu yazıda, Windows lisans yönetimini PowerShell üzerinden nasıl otomatize edeceğini, toplu aktivasyon işlemlerini nasıl yöneteceğini ve üretim ortamlarında işe yarayan gerçek senaryoları ele alacağız.
slmgr Nedir ve Neden PowerShell ile Kullanmalısın?
slmgr.vbs (Software Licensing Manager), Windows’un yerleşik lisans yönetim aracıdır. VBScript tabanlı bu araç, lisans aktivasyonu, KMS yapılandırması, lisans durumu sorgulama gibi işlemleri komut satırından yapmanı sağlar. Tek başına kullanılabilir ama PowerShell ile entegre ettiğinde asıl gücü ortaya çıkıyor.
Neden PowerShell? Çünkü slmgr.vbs‘yi doğrudan çağırabilirsin, çıktıları işleyebilirsin, döngüler yazabilirsin, uzak makinelere bağlanabilirsin ve tüm süreci loglayabilirsin. Ayrıca WMI/CIM üzerinden lisans bilgilerine doğrudan erişim de mümkün. Bu da sana hem slmgr komutlarını hem de daha derin bir sorgu mekanizması sunuyor.
Temel slmgr Parametreleri
Önce slmgr.vbs‘nin temel parametrelerini PowerShell bağlamında nasıl kullandığımıza bakalım. Bu parametreler her Windows yöneticisinin ezbere bilmesi gereken şeyler.
-dli: Temel lisans bilgilerini gösterir. Ürün adı, aktivasyon kimliği, lisans durumu gibi özet bilgiler verir.
-dlv: Detaylı lisans bilgilerini gösterir. KMS sunucu bilgileri, aktivasyon sayaçları, lisans süresi gibi kapsamlı veriler içerir.
-xpr: Lisansın süresini kontrol eder. Makinenin ne zaman yeniden aktivasyon gerektireceğini gösterir.
-ipk: Yeni bir ürün anahtarı yükler. Parametrenin ardından ürün anahtarı belirtilir.
-upk: Mevcut ürün anahtarını kaldırır.
-ato: Aktivasyon işlemini başlatır.
-skms: KMS sunucusunu ve portunu belirler.
-ckms: Yapılandırılmış KMS sunucusunu temizler.
-rearm: Değerlendirme süresini sıfırlar. Dikkatli kullanılmalıdır.
-dti: KMS aktivasyonu için gerekli Kurulum Kimliğini alır.
-atp: Telefon aktivasyonu için Onay Kimliği girer.
Lisans Durumunu Kontrol Etmek
En temel senaryodan başlayalım: Tek bir makinenin lisans durumunu sorgulamak.
# Temel lisans bilgisi
cscript C:WindowsSystem32slmgr.vbs -dli
# Detayli lisans bilgisi
cscript C:WindowsSystem32slmgr.vbs -dlv
# Lisans suresi
cscript C:WindowsSystem32slmgr.vbs -xpr
Bu komutlar bir pencere açarak sonucu gösterir. Ama PowerShell scriptlerinde bunu otomatize etmek için çıktıyı yakalamanız ve işlemeniz gerekir. Bunun için WMI/CIM yolu çok daha temiz:
# WMI uzerinden lisans durumu sorgulama
$LisansBilgisi = Get-WmiObject -Class SoftwareLicensingProduct `
-Filter "Name like 'Windows%'" |
Where-Object { $_.PartialProductKey -ne $null }
foreach ($lisans in $LisansBilgisi) {
Write-Host "Urun Adi: $($lisans.Name)"
Write-Host "Aktivasyon Durumu: $($lisans.LicenseStatus)"
Write-Host "Kismi Anahtar: $($lisans.PartialProductKey)"
Write-Host "KMS Sunucusu: $($lisans.DiscoveredKeyManagementServiceMachineName)"
Write-Host "---"
}
LicenseStatus değerleri şu anlama gelir:
- 0: Lisanssız
- 1: Lisanslı (Aktif)
- 2: OOB Grace (Kutu dışı tolerans süresi)
- 3: OOT Grace (Tolerans süresi dolmak üzere)
- 4: Non-Genuine Grace (Orijinal olmayan)
- 5: Bildirim modu
- 6: Genişletilmiş Grace
Toplu Lisans Durumu Sorgulama Scripti
Gerçek hayatta tek bir makinenin durumunu elle kontrol etmiyorsun. Onlarca, belki yüzlerce sunucuyu kontrol etmen gerekiyor. İşte bunun için kullanabileceğin kapsamlı bir script:
# Toplu lisans kontrolu - makine listesinden okuma
param(
[string]$MakinelListesi = "C:Scriptssunucular.txt",
[string]$LogDosyasi = "C:Scriptslisans_raporu_$(Get-Date -Format 'yyyyMMdd').csv"
)
# Durum kodlarini insan okuyabilir formata cevir
function Get-LisansDurumu {
param([int]$KodDeger)
switch ($KodDeger) {
0 { return "Lisanssiz" }
1 { return "Aktif" }
2 { return "Grace Suresi (OOB)" }
3 { return "Grace Suresi Bitmek Uzere" }
4 { return "Orijinal Degil" }
5 { return "Bildirim Modu" }
6 { return "Uzatilmis Grace" }
default { return "Bilinmiyor ($KodDeger)" }
}
}
$Sonuclar = @()
$Makineler = Get-Content $MakinelListesi
foreach ($Makine in $Makineler) {
Write-Host "Kontrol ediliyor: $Makine" -ForegroundColor Cyan
try {
$LisansVerisi = Get-WmiObject -Class SoftwareLicensingProduct `
-ComputerName $Makine `
-Filter "Name like 'Windows%'" `
-ErrorAction Stop |
Where-Object { $_.PartialProductKey -ne $null }
foreach ($veri in $LisansVerisi) {
$Sonuclar += [PSCustomObject]@{
Makine = $Makine
UrunAdi = $veri.Name
Durum = Get-LisansDurumu $veri.LicenseStatus
KismiAnahtar = $veri.PartialProductKey
KMSSunucu = $veri.DiscoveredKeyManagementServiceMachineName
KMSPort = $veri.DiscoveredKeyManagementServiceMachinePort
SorguZamani = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Hata = ""
}
}
}
catch {
Write-Warning "HATA - $Makine : $($_.Exception.Message)"
$Sonuclar += [PSCustomObject]@{
Makine = $Makine
UrunAdi = "N/A"
Durum = "Erisim Hatasi"
KismiAnahtar = "N/A"
KMSSunucu = "N/A"
KMSPort = "N/A"
SorguZamani = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Hata = $_.Exception.Message
}
}
}
# CSV olarak kaydet
$Sonuclar | Export-Csv -Path $LogDosyasi -NoTypeInformation -Encoding UTF8
Write-Host "`nRapor kaydedildi: $LogDosyasi" -ForegroundColor Green
# Ozet goster
$Sonuclar | Group-Object Durum |
Select-Object Name, Count |
Format-Table -AutoSize
Bu script, bir metin dosyasından sunucu isimlerini okur, her birinin lisans durumunu sorgular ve sonuçları CSV dosyasına kaydeder. Haftalık zamanlanmış görev olarak çalıştırdığında lisans altyapının sürekli takibini yapabilirsin.
KMS Yapılandırması ve Yönetimi
Kurumsal ortamlarda büyük ihtimalle KMS (Key Management Service) kullanıyorsunuzdur. KMS yapılandırmasını PowerShell ile yönetmek hem hızlı hem de tutarlı sonuçlar veriyor.
# KMS sunucusunu yapilandir
function Set-KMSYapılandirmasi {
param(
[string]$KMSSunucu,
[int]$Port = 1688,
[string[]]$HedefMakineler
)
foreach ($Makine in $HedefMakineler) {
Write-Host "KMS yapilandiriliyor: $Makine" -ForegroundColor Yellow
try {
# Uzak makinede KMS sunucusunu ayarla
$SonucKMS = Invoke-Command -ComputerName $Makine -ScriptBlock {
param($Sunucu, $PortNo)
# Mevcut KMS temizle
cscript C:WindowsSystem32slmgr.vbs -ckms | Out-Null
# Yeni KMS sunucusu ayarla
cscript C:WindowsSystem32slmgr.vbs -skms "$Sunucu`:$PortNo" | Out-Null
# Aktivasyonu baslat
$AtoSonuc = cscript C:WindowsSystem32slmgr.vbs -ato 2>&1
return $AtoSonuc
} -ArgumentList $KMSSunucu, $Port -ErrorAction Stop
Write-Host "Basarili: $Makine - $SonucKMS" -ForegroundColor Green
}
catch {
Write-Error "Hata: $Makine - $($_.Exception.Message)"
}
}
}
# Kullanim ornegi
$SunucuListesi = @("SUNUCU01", "SUNUCU02", "SUNUCU03")
Set-KMSYapılandirmasi -KMSSunucu "kms.sirket.local" -Port 1688 -HedefMakineler $SunucuListesi
Ürün Anahtarı Yükleme ve Değiştirme
Lisans anahtarı değiştirmek gerektiğinde, özellikle toplu işlemlerde, aşağıdaki yaklaşım çok işe yarıyor. Dikkat: Ürün anahtarlarını script içine düz metin olarak yazma. Güvenli bir yerden oku ya da SecureString kullan.
# Guvenli urun anahtari yukleme
function Install-UrunAnahtari {
param(
[Parameter(Mandatory=$true)]
[string]$Makine,
[Parameter(Mandatory=$true)]
[string]$UrunAnahtari
)
# Anahtar formatini dogrula (XXXXX-XXXXX-XXXXX-XXXXX-XXXXX)
$AnahtarPattern = '^([A-Z0-9]{5}-){4}[A-Z0-9]{5}$'
if ($UrunAnahtari -notmatch $AnahtarPattern) {
Write-Error "Gecersiz anahtar formati: $UrunAnahtari"
return $false
}
try {
$Sonuc = Invoke-Command -ComputerName $Makine -ScriptBlock {
param($Anahtar)
# Eski anahtari kaldir
cscript C:WindowsSystem32slmgr.vbs -upk | Out-Null
Start-Sleep -Seconds 2
# Yeni anahtari yukle
$YukleSonuc = cscript C:WindowsSystem32slmgr.vbs -ipk $Anahtar 2>&1
# Aktivasyonu baslat
$AktivasySonuc = cscript C:WindowsSystem32slmgr.vbs -ato 2>&1
return @{
Yukleme = $YukleSonuc -join " "
Aktivasyon = $AktivasySonuc -join " "
}
} -ArgumentList $UrunAnahtari -ErrorAction Stop
Write-Host "Anahtar yuklendi: $Makine" -ForegroundColor Green
Write-Host "Aktivasyon: $($Sonuc.Aktivasyon)" -ForegroundColor Cyan
return $true
}
catch {
Write-Error "Anahtar yuklenemedi - $Makine : $($_.Exception.Message)"
return $false
}
}
Aktivasyon Sorunlarını Otomatik Giderme
Prodüksiyon ortamında en çok karşılaştığım senaryolardan biri: sabah iş başında bir grup makinenin aktivasyon durumunun bozulmuş olduğunu fark etmek. Bunun için proaktif bir izleme ve otomatik düzeltme scripti kullanıyorum:
# Aktivasyon sorunlarini tespit ve otomatik duzelt
param(
[string[]]$Makineler,
[string]$KMSSunucu = "kms.sirket.local",
[switch]$OtomatikDuzelt,
[string]$RaporYolu = "C:ScriptsRaporlar"
)
if (-not (Test-Path $RaporYolu)) {
New-Item -ItemType Directory -Path $RaporYolu | Out-Null
}
$SorunluMakineler = @()
$RaporZamani = Get-Date -Format "yyyyMMdd_HHmmss"
foreach ($Makine in $Makineler) {
try {
$LisansBilgi = Get-WmiObject -Class SoftwareLicensingProduct `
-ComputerName $Makine `
-Filter "Name like 'Windows%'" |
Where-Object { $_.PartialProductKey -ne $null }
$Durum = $LisansBilgi.LicenseStatus
if ($Durum -ne 1) {
Write-Warning "$Makine - Sorunlu durum: $Durum"
$SorunluMakineler += $Makine
if ($OtomatikDuzelt) {
Write-Host "Duzeltme deneniyor: $Makine" -ForegroundColor Yellow
Invoke-Command -ComputerName $Makine -ScriptBlock {
param($KMS)
# KMS sunucusunu yeniden ayarla
cscript C:WindowsSystem32slmgr.vbs -ckms | Out-Null
cscript C:WindowsSystem32slmgr.vbs -skms $KMS | Out-Null
cscript C:WindowsSystem32slmgr.vbs -ato | Out-Null
# Lisanslama servisini yeniden baslat
Restart-Service -Name "sppsvc" -Force
Start-Sleep -Seconds 5
cscript C:WindowsSystem32slmgr.vbs -ato | Out-Null
} -ArgumentList $KMSSunucu
# Duzeltme sonrasinda tekrar kontrol et
Start-Sleep -Seconds 10
$YeniDurum = (Get-WmiObject -Class SoftwareLicensingProduct `
-ComputerName $Makine `
-Filter "Name like 'Windows%'" |
Where-Object { $_.PartialProductKey -ne $null }).LicenseStatus
if ($YeniDurum -eq 1) {
Write-Host "Duzeltildi: $Makine" -ForegroundColor Green
$SorunluMakineler = $SorunluMakineler | Where-Object { $_ -ne $Makine }
}
else {
Write-Error "Duzeltilemedi: $Makine (Durum: $YeniDurum)"
}
}
}
else {
Write-Host "$Makine - OK" -ForegroundColor Green
}
}
catch {
Write-Error "Erisim hatasi: $Makine - $($_.Exception.Message)"
$SorunluMakineler += $Makine
}
}
# Sorunlu makine raporu kaydet
if ($SorunluMakineler.Count -gt 0) {
$RaporDosyasi = Join-Path $RaporYolu "sorunlu_makineler_$RaporZamani.txt"
$SorunluMakineler | Out-File -FilePath $RaporDosyasi -Encoding UTF8
Write-Host "`nSorunlu makine sayisi: $($SorunluMakineler.Count)" -ForegroundColor Red
Write-Host "Rapor kaydedildi: $RaporDosyasi" -ForegroundColor Yellow
}
else {
Write-Host "`nTum makineler aktif!" -ForegroundColor Green
}
KMS Sunucu Durumunu İzlemek
KMS sunucunun sağlığını izlemek de kritik bir görev. Yeterli aktivasyon sayısına ulaşılıp ulaşılmadığını ve sunucunun düzgün çalışıp çalışmadığını düzenli kontrol etmelisin:
# KMS sunucu durumu ve aktivasyon sayaci kontrolu
function Get-KMSSunucuDurumu {
param([string]$KMSSunucu)
try {
$KMSVerisi = Get-WmiObject -Class SoftwareLicensingProduct `
-ComputerName $KMSSunucu `
-Filter "ApplicationId='55c92734-d682-4d71-983e-d6ec3f16059f' AND LicenseIsAddon=False" `
-ErrorAction Stop
foreach ($urun in $KMSVerisi | Where-Object { $_.LicenseStatus -eq 1 }) {
Write-Host "=== KMS Sunucu Bilgisi ===" -ForegroundColor Cyan
Write-Host "Sunucu: $KMSSunucu"
Write-Host "Urun: $($urun.Name)"
# Mevcut aktivasyon sayisi
$AktivasyonSayaci = Invoke-Command -ComputerName $KMSSunucu -ScriptBlock {
$kayit = Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionSoftwareProtectionPlatform" `
-ErrorAction SilentlyContinue
return $kayit
}
Write-Host "KMS Port: 1688"
Write-Host "Durum: Aktif"
}
}
catch {
Write-Error "KMS sunucuya erisim hatasi: $($_.Exception.Message)"
}
# Portun acik olup olmadigini kontrol et
$PortKontrol = Test-NetConnection -ComputerName $KMSSunucu -Port 1688 -WarningAction SilentlyContinue
if ($PortKontrol.TcpTestSucceeded) {
Write-Host "KMS Port 1688: ACIK" -ForegroundColor Green
}
else {
Write-Host "KMS Port 1688: KAPALI - Guvvenlik duvari kuralini kontrol edin!" -ForegroundColor Red
}
}
Get-KMSSunucuDurumu -KMSSunucu "kms.sirket.local"
Zamanlanmış Görev ile Otomatik Lisans Takibi
Bu scriptlerin hepsini zamanlanmış görev olarak çalıştırmanı öneririm. Aşağıdaki script, günlük lisans kontrolü için zamanlanmış görev oluşturuyor:
# Zamanlanmis gorev olustur - gunluk lisans kontrolu
$GorevAdi = "GunlukLisansKontrolu"
$ScriptYolu = "C:Scriptslisans_kontrolu.ps1"
$ZamanlanmisZaman = "07:00"
# Gorev ayarlari
$Eylem = New-ScheduledTaskAction `
-Execute "PowerShell.exe" `
-Argument "-NonInteractive -NoProfile -ExecutionPolicy Bypass -File `"$ScriptYolu`""
$Tetikleyici = New-ScheduledTaskTrigger `
-Daily `
-At $ZamanlanmisZaman
$Ayarlar = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Hours 2) `
-RestartCount 3 `
-RestartInterval (New-TimeSpan -Minutes 10) `
-StartWhenAvailable
$Eleman = New-ScheduledTaskPrincipal `
-UserId "DOMAINServiceHesabi" `
-LogonType Password `
-RunLevel Highest
# Gorevi kaydet
Register-ScheduledTask `
-TaskName $GorevAdi `
-Action $Eylem `
-Trigger $Tetikleyici `
-Settings $Ayarlar `
-Principal $Eleman `
-Description "Gunluk Windows lisans durum kontrolu ve raporlama" `
-Force
Write-Host "Zamanlanmis gorev olusturuldu: $GorevAdi" -ForegroundColor Green
Write-Host "Calisma saati: $ZamanlanmisZaman" -ForegroundColor Cyan
Pratik İpuçları ve Dikkat Edilmesi Gerekenler
Yıllarca bu araçlarla çalıştıktan sonra öğrendiğim bazı önemli noktalar var.
WMI yerine CIM tercih et: Yeni ortamlarda Get-WmiObject yerine Get-CimInstance kullanmaya başla. Hem daha hızlı hem de PowerShell 6+ ile uyumlu.
cscript ile çalıştır: slmgr.vbs‘yi her zaman cscript ile çağır, wscript ile değil. wscript GUI penceresi açar, cscript konsola çıktı verir; scriptlerde işlenebilir.
Güvenlik duvarı kurallarını unutma: Uzak makinelerde WMI sorgusu yapabilmek için 135 portunu ve dinamik RPC portlarını açman gerekiyor. Aksi halde “Access Denied” veya timeout hataları alırsın.
Servis hesabı yetkilerini kontrol et: Lisans yönetimi işlemleri için Administrator yetkisi gerekiyor. Uzak makinelerde bu işlemleri yapacak servis hesabının domain admin veya lokal admin olması şart.
rearm işlemini acil durumlar için sakla: slmgr.vbs -rearm komutu değerlendirme süresini uzatır ama sınırlı sayıda kullanılabilir. Bunu rutin bir işlem haline getirme.
Log yönetimini ihmal etme: Lisans değişiklikleri denetim açısından kritik. Her aktivasyon, anahtar değişikliği ve hata mutlaka loglanmalı. Event Log’a da yazmayı düşün:
# Olay gunlugune lisans degisikligini kaydet
function Write-LisansOlayi {
param(
[string]$Mesaj,
[string]$OlayTuru = "Information"
)
$KaynakAdi = "LisansYonetimi"
if (-not [System.Diagnostics.EventLog]::SourceExists($KaynakAdi)) {
New-EventLog -LogName Application -Source $KaynakAdi
}
Write-EventLog -LogName Application `
-Source $KaynakAdi `
-EventId 1000 `
-EntryType $OlayTuru `
-Message $Mesaj
}
Write-LisansOlayi -Mesaj "KMS aktivasyonu tamamlandi: SUNUCU01" -OlayTuru "Information"
GVLK anahtarlarını bilmek: KMS aktivasyonu için Generic Volume License Key (GVLK) anahtarları gereklidir. Bu anahtarlar Microsoft’un dokümantasyonunda halka açık paylaşılmıştır; üretim anahtarı değildir, sadece KMS aktivasyonunu tetiklemek için kullanılır.
Test ortamında dene: Özellikle toplu anahtar değiştirme veya rearm işlemlerini üretim ortamına uygulamadan önce mutlaka test ortamında dene.
Sonuç
PowerShell ile Windows lisans yönetimi, büyük ölçekli ortamlarda hem zamandan tasarruf sağlıyor hem de tutarlılığı garantiliyor. slmgr.vbs komutlarını PowerShell döngüleriyle, WMI/CIM sorgulamalarıyla ve hata yönetimi mekanizmalarıyla bir araya getirdiğinde; yüzlerce makinenin lisans durumunu dakikalar içinde görebilir, sorunları otomatik olarak düzeltebilir ve tüm süreci izlenebilir hale getirebilirsin.
Bu yazıdaki scriptleri doğrudan kopyalayıp yapıştırma. Kendi ortamına göre uyarla, özellikle KMS sunucu adlarını, makine listelerini ve servis hesaplarını değiştir. Test ortamında çalıştır, logları incele ve ancak ondan sonra prodüksiyona al. Lisans yönetimi kritik bir süreç; otomasyonun faydalarından yararlanırken dikkatli ve sistematik olmak gerekiyor. Herhangi bir adımda takılırsan event log ve slmgr -dlv çıktısı genellikle sana doğru yönü gösterir.