WSUS
Auto Approve / Decline Updates
Bu script filitreye girecek güncellemelerin otomatik olarak onaylanması ve filitre dışında kalan (Days den önceki) güncellemelerin reddedilmesini sağlar. Scripte parametre olarak gün, ürün(ler), sınıflandırma(lar), güncelleme adı (içerir şeklinde yazılabilir) ve Hedef bilgisayar grubu verilebilir. Boş bırakılan parametre değerlendirmeye alınmaz.
function Manage-WsusUpdates {
<#
.SYNOPSIS
WSUS güncellemelerini filtreleyip Approve/Decline eder. Declined olanları gerçek anlamda “undecline + approve” yapar.
#>
[CmdletBinding()]
param (
[int]$Days = 30,
[string[]]$Products,
[ValidateSet('Exact','Like','Regex')]
[string]$ProductMatchMode = 'Like',
[string[]]$Classifications,
[string[]]$Titles,
[string]$TargetGroupName = "All Computers",
[string]$WsusServer = "localhost",
[bool]$UseSsl = $false,
[int]$Port = 8530,
[string]$RequiredFilter, # "gt 0", "ge 1", "eq 0" ...
[switch]$IncludeSubgroupsRequired, # Required hesaplamasında alt grupları dahil et
[bool]$AutoUndeclineBeforeApprove = $true, # declined ise önce gerçek undecline et, sonra approve
[switch]$AllowDecline, # cutoff öncesi uygunları decline et
[switch]$SkipExpired, # expired güncellemeleri atla
[switch]$SkipSuperseded, # superseded güncellemeleri atla
[switch]$DryRun
)
# Assembly (PS 5.1)
$null = [Reflection.Assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
# Connect
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($WsusServer, $UseSsl, $Port)
$cutoffDate = (Get-Date).AddDays(-$Days)
# Target group
$targetGroup = $wsus.GetComputerTargetGroups() | Where-Object { $_.Name -eq $TargetGroupName }
if (-not $targetGroup) { Write-Error "Target WSUS group not found: $TargetGroupName"; return }
# Universe
$allUpdates = $wsus.GetUpdates()
# Counters
$scanned = 0; $passProduct = 0; $passClass = 0; $passTitle = 0; $passRequired = 0
$approvedCount = 0; $declinedCount = 0; $skippedByRequired = 0
$skippedExpired = 0; $skippedSuperseded = 0; $undeclineFailures = 0
foreach ($update in $allUpdates) {
$scanned++
# Optional skips: expired / superseded
if ($SkipExpired.IsPresent -and $update.IsExpired) { $skippedExpired++; continue }
if ($SkipSuperseded.IsPresent -and $update.IsSuperseded) { $skippedSuperseded++; continue }
# Product match
$matchesProduct = $true
if ($Products -and $Products.Count -gt 0) {
$matchesProduct = $false
foreach ($prodTitle in $update.ProductTitles) {
foreach ($filter in $Products) {
switch ($ProductMatchMode) {
'Exact' { if ($prodTitle -eq $filter) { $matchesProduct = $true } }
'Like' { if ($prodTitle -like ("*" + $filter + "*")) { $matchesProduct = $true } }
'Regex' { if ($prodTitle -match $filter) { $matchesProduct = $true } }
}
if ($matchesProduct) { break }
}
if ($matchesProduct) { break }
}
}
if (-not $matchesProduct) { continue } else { $passProduct++ }
# Classification match
$matchesClass = $true
if ($Classifications -and $Classifications.Count -gt 0) {
$matchesClass = ($Classifications -contains $update.UpdateClassificationTitle)
}
if (-not $matchesClass) { continue } else { $passClass++ }
# Title match
$matchesTitle = $true
if ($Titles -and $Titles.Count -gt 0) {
$matchesTitle = $false
foreach ($tf in $Titles) { if ($update.Title -like ("*" + $tf + "*")) { $matchesTitle = $true; break } }
}
if (-not $matchesTitle) { continue } else { $passTitle++ }
# Required (Needed) filter
$matchesRequired = $true
if ($RequiredFilter -and $RequiredFilter.Trim().Length -gt 0) {
$op = $null; $thrText = $null
$parts = $RequiredFilter -split '\s+', 2
if ($parts.Length -ne 2) {
Write-Warning "Invalid RequiredFilter format: '$RequiredFilter'. Use: 'gt 0', 'ge 1', 'eq 0'..."
$matchesRequired = $false
} else { $op,$thrText = $parts[0],$parts[1] }
$requiredCount = 0
if ($matchesRequired) {
$summary = $null
try {
$summary = $update.GetSummaryForComputerTargetGroup($targetGroup, [bool]$IncludeSubgroupsRequired.IsPresent)
} catch {
try {
$sumAll = $update.GetSummaryPerComputerTargetGroup()
if ($sumAll) {
$summary = $sumAll | Where-Object { $_.ComputerTargetGroupId -eq $targetGroup.Id } | Select-Object -First 1
}
} catch { $summary = $null }
}
$requiredCount = if ($summary) { [int]$summary.NotInstalledCount } else { 0 }
$thr = 0
if (-not [int]::TryParse($thrText, [ref]$thr)) {
Write-Warning "Invalid RequiredFilter threshold: '$thrText' (must be integer)."
$matchesRequired = $false
} else {
switch ($op.ToLower()) {
'eq' { $matchesRequired = ($requiredCount -eq $thr) }
'ne' { $matchesRequired = ($requiredCount -ne $thr) }
'gt' { $matchesRequired = ($requiredCount -gt $thr) }
'ge' { $matchesRequired = ($requiredCount -ge $thr) }
'lt' { $matchesRequired = ($requiredCount -lt $thr) }
'le' { $matchesRequired = ($requiredCount -le $thr) }
default { Write-Warning "Invalid operator '$op' (eq,ne,gt,ge,lt,le)"; $matchesRequired = $false }
}
}
}
if (-not $matchesRequired) { $skippedByRequired++; continue } else { $passRequired++ }
}
# Approve / Decline
$creationDate = $update.CreationDate
$isDeclined = $update.IsDeclined
if ($creationDate -ge $cutoffDate) {
# --- APPROVE path ---
if ($isDeclined -and $AutoUndeclineBeforeApprove) {
if ($DryRun) {
Write-Host "[DRY-RUN] Would UNDECLINE: $($update.Title)"
$isDeclined = $false # DryRun’da devam edelim
} else {
$undeclined = $false
# A) İç arayüze cast ederek SetDeclined(false) çağır
try {
$intfType = [type]'Microsoft.UpdateServices.Internal.BaseApi.IUpdate'
if ($intfType) {
$iu = $update -as $intfType
if ($iu) {
$iu.SetDeclined($false)
$update.Refresh()
if (-not $update.IsDeclined) { $undeclined = $true }
}
}
} catch { }
# B) NonPublic reflection ile SetDeclined(false)
if (-not $undeclined) {
try {
$flags = [System.Reflection.BindingFlags]'Instance,NonPublic'
$m = $update.GetType().GetMethod('SetDeclined', $flags, $null, @([bool]), $null)
if ($m) {
[void]$m.Invoke($update, @($false))
$update.Refresh()
if (-not $update.IsDeclined) { $undeclined = $true }
}
} catch { }
}
# C) (son çare) Approve(NotApproved) + Refresh — bazı ortamlarda flag’i temizliyor
if (-not $undeclined) {
try {
$update.Approve([Microsoft.UpdateServices.Administration.UpdateApprovalAction]::NotApproved, $targetGroup) | Out-Null
$update.Refresh()
if (-not $update.IsDeclined) { $undeclined = $true }
} catch { }
}
if ($undeclined) {
Write-Host "Undeclined: $($update.Title)"
$isDeclined = $false
} else {
Write-Warning "Failed to undecline: $($update.Title). Skipping approve."
$undeclineFailures++
continue
}
}
}
# Onay zaten var mı?
$alreadyApproved = $false
foreach ($appr in $update.GetUpdateApprovals()) {
if (($appr.ComputerTargetGroupId -eq $targetGroup.Id) -and
($appr.Action -eq [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install)) {
$alreadyApproved = $true; break
}
}
if (-not $alreadyApproved) {
if ($DryRun) {
Write-Host "[DRY-RUN] Would APPROVE: $($update.Title)"
} else {
try {
$update.Approve([Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install, $targetGroup) | Out-Null
Write-Host "Approved: $($update.Title)"
$approvedCount++
} catch {
Write-Warning "Error while approving: $($update.Title) - $($_.Exception.Message)"
}
}
} else {
Write-Host "Already approved: $($update.Title)"
}
}
elseif ($creationDate -lt $cutoffDate -and -not $isDeclined -and $AllowDecline.IsPresent) {
# --- DECLINE path ---
if ($DryRun) {
Write-Host "[DRY-RUN] Would DECLINE: $($update.Title)"
} else {
try { $update.Decline(); Write-Host "Declined: $($update.Title)"; $declinedCount++ }
catch { Write-Warning "Error while declining: $($update.Title) - $($_.Exception.Message)" }
}
}
}
# Özet
if ($DryRun) { Write-Host "`nSimulation completed. No updates were actually approved or declined." }
Write-Host ("Scanned: {0} | Pass(Product): {1} | Pass(Class): {2} | Pass(Title): {3} | Pass(Required): {4} | Skipped(Expired): {5} | Skipped(Superseded): {6} | UndeclineFailed: {7}" -f `
$scanned, $passProduct, $passClass, $passTitle, $passRequired, $skippedExpired, $skippedSuperseded, $undeclineFailures)
if (-not $DryRun) {
Write-Host "Operation completed. Total approved: $approvedCount | Total declined: $declinedCount | Skipped by RequiredFilter: $skippedByRequired"
}
}
1) Genel Bakış
Manage-WsusUpdates, WSUS üzerindeki güncellemeleri dinamik filtrelerle (Ürün, Sınıflandırma, Başlık, “Required/Needed” koşulu) tarar ve:
Kesim tarihinden (Days) yeni olan uygun güncellemeleri Approve (Install) eder.
İsterseniz, kesim tarihinden eski olan uygun güncellemeleri Decline eder.
Declined durumundaki güncellemeleri, onay vermeden önce gerçek anlamda “undecline” eder ve ardından Install ile onaylar (varsayılan açık).
Bu doküman, fonksiyonu script dışında referans olarak kullanmanız için hazırlanmıştır.
2) Sistem Gereksinimleri & Önkoşullar
PowerShell 5.1
WSUS Administration Assembly (sunucuda WSUS rolü/araçları yüklü olmalı):
Microsoft.UpdateServices.Administration
WSUS üzerinde yeterli yetkilere sahip bir hesap (güncelleme onayı/decline işlemleri için WSUS Administrator)
3) Parametreler (Tam Referans)
Days
int
30
Kesim gün sayısı. “Yeni” = CreationDate >= (Today - Days)
. “Eski” = CreationDate < (Today - Days)
.
Products
string[]
—
Ürün adına göre filtre. ProductMatchMode
ile Exact/Like/Regex eşleştirme.
ProductMatchMode
Exact | Like | Regex
Like
Ürün eşleşme modu. Like = kısmi eşleşme (*parça*
).
Classifications
string[]
—
Güncelleme sınıfları. Tam eşleşme bekler (örn. “Security Updates”).
Titles
string[]
—
Başlıkta geçen parçaya göre filtre (kısmi eşleşme -like "*x*"
).
TargetGroupName
string
All Computers
Onay/decline işlemlerinin hedefleneceği WSUS grubu.
WsusServer
string
localhost
WSUS sunucu adı/FQDN.
UseSsl
bool
false
WSUS’a SSL ile bağlan. (Genelde 8531)
Port
int
8530
WSUS portu. SSL için genelde 8531
.
RequiredFilter
string
—
“op sayı” formatı. Örn: "gt 0"
, "ge 1"
, "eq 0"
. Ayrıntı için §4.
IncludeSubgroupsRequired
switch
—
Required/Needed sayımında alt grupları da dahil eder.
AutoUndeclineBeforeApprove
bool
true
Declined olan update’i onaylamadan önce gerçek undecline yapar.
AllowDecline
switch
—
Kesim tarihinden eski ve filtreleri geçen güncellemeleri Decline eder.
SkipExpired
switch
—
Expired güncellemeleri baştan atlar.
SkipSuperseded
switch
—
Superseded güncellemeleri baştan atlar.
DryRun
switch
—
Simülasyon modudur: Approve/Decline yapmaz, ne yapacağını yazar.
Not: Switch parametrelere :$true / :$false
biçiminde değer vermek güvenlidir (örn. -AllowDecline:$false
). Sadece -AllowDecline $false
yazarsanız, PowerShell bunu sonradan gelen konumsal parametreye atayabilir.
4) RequiredFilter Sözdizimi
Biçim:
"op sayı"
Operatörler:
eq
: eşitne
: eşit değilgt
: büyükge
: büyük-eşitlt
: küçükle
: küçük-eşit
Örnekler:
"gt 0"
→ Required/Needed sayısı 0’dan büyük olanlar."ge 1"
→ 1 veya daha fazla gerekli istemcisi olanlar."eq 0"
→ hiç gerek duyulmayan güncellemeler (rapor amaçlı veya decline ile birleştirilebilir).
Hesaplama:
GetSummaryForComputerTargetGroup($targetGroup, $IncludeSubgroupsRequired)
ile alınanNotInstalledCount
değeri kullanılır.
5) Onay/Ret (Approve/Decline) Davranışı
Approve (Install):
CreationDate >= cutoff
(yeni) ve tüm filtreleri geçen güncellemeler hedef grupta Install ile onaylanır.Zaten Install onayı varsa “Already approved” yazılır.
Decline (opsiyonel;
-AllowDecline
):CreationDate < cutoff
(eski) ve filtreleri geçen güncellemeler Decline edilir.SkipExpired / SkipSuperseded açık ise, bu tür güncellemeler önce atlandığı için decline yoluna hiç girmez.
6) “Declined → Undecline → Approve” Mantığı
Declined bir güncellemeyi doğrudan Install ile approve edemezsiniz. Script şu sırayla dener (AutoUndeclineBeforeApprove = true ise):
Internal arayüz yolu:
Microsoft.UpdateServices.Internal.BaseApi.IUpdate.SetDeclined(false)
Reflection (NonPublic):
SetDeclined(false)
metodunu yansıma ile çağırma“Konsol eşdeğeri” fallback:
Approve(NotApproved, $group)
ardındanRefresh()
Her adımda başarı sağlanamazsa:
WARNING: Failed to undecline: <Title>. Skipping approve.
Öneri: Çoğu durumda Expired/Superseded paketleri zaten üretken değildir;
-SkipExpired -SkipSuperseded
kullanmanız akışı temizler.
7) Çıktılar & Sayaçlar
Komut sonunda (veya DryRun’da) özet verir:
Scanned
— toplam taranan güncellemePass(Product)
— ürün filtrelerini geçenPass(Class)
— sınıflandırma filtrelerini geçenPass(Title)
— başlık filtrelerini geçenPass(Required)
— RequiredFilter koşulunu geçenSkipped(Expired)
—-SkipExpired
nedeniyle atlananSkipped(Superseded)
—-SkipSuperseded
nedeniyle atlananUndeclineFailed
— undecline denemeleri başarısız olan sayısıİşlem özeti:
Operation completed. Total approved: X | Total declined: Y | Skipped by RequiredFilter: Z
8) Kullanım Senaryoları (Örnekler)
8.1) Son 30 gün & Required > 0 olanları approve et (decline yok)
Manage-WsusUpdates -Days 30 `
-RequiredFilter 'gt 0' `
-AllowDecline:$false
8.2) 1 yıl geriye bak, Tools/Documents ürünleri, alt gruplar dahil, approve et
Manage-WsusUpdates -Days 365 `
-Products @('Tools','Documents') -ProductMatchMode Like `
-IncludeSubgroupsRequired `
-RequiredFilter 'gt 0' `
-AllowDecline:$false
8.3) SSL’li WSUS, belirli grup, “Cumulative” başlıklı güvenlik güncellemelerini onayla
Manage-WsusUpdates -Days 60 `
-WsusServer 'arksup.arksoft.local' -UseSsl:$true -Port 8531 `
-TargetGroupName 'Servers' `
-Classifications @('Security Updates') `
-Titles @('Cumulative') `
-RequiredFilter 'ge 1'
8.4) Eski güncellemeleri decline et (ör. 120 günden eski & hiç ihtiyaç yok)
Manage-WsusUpdates -Days 120 `
-RequiredFilter 'eq 0' `
-AllowDecline `
-SkipExpired -SkipSuperseded
8.5) DryRun ile güvenli prova
Manage-WsusUpdates -Days 180 `
-Products @('Windows 11','Windows Server 2022') `
-Classifications @('Security Updates','Critical Updates') `
-RequiredFilter 'ge 1' `
-DryRun
8.6) Undecline + Approve akışı açık (varsayılan) — pratik örnek
Manage-WsusUpdates -Days 365 `
-Products @('Tools','Documents') -ProductMatchMode Like `
-IncludeSubgroupsRequired -RequiredFilter 'gt 0' `
-SkipExpired -SkipSuperseded `
-AllowDecline:$false `
-AutoUndeclineBeforeApprove:$true
9) En İyi Uygulamalar
Önce DryRun çalıştırın; eleme ve sayımları görün.
Products
için Like modu günlük kullanıma çok uygundur (kısmi eşleşme).Grubunuz hiyerarşili ise
-IncludeSubgroupsRequired
açmayı düşünün; aksi halde üst gruptaNotInstalledCount
0 görünebilir.Expired/Superseded paketleri genelde üretken değildir;
-SkipExpired -SkipSuperseded
kullanın.Switch parametrelerinde
-SwitchName:$false
yazımı “yanlış konumsal bağlanma” hatalarını önler.
10) Sık Karşılaşılan Sorunlar & Çözümler
10.1) “0 approved | 0 declined” (ama filtreye uyan güncellemeler var)
Pass(Product/Class/Title/Required)
sayaçlarına bakın: Hangi aşamada eleniyor?Products
yanlış yazılmış olabilir. Like modunda kısmi eşleşme yapın veya gerçek ProductTitles listesini çıkarıp kontrol edin.RequiredFilter
koşulunuz dar olabilir (örn. ge 1 yerine gt 0 deneyin).TargetGroupName
doğru mu? Onay verdiğiniz grup gerçekten hedeflediğiniz mi?
10.2) “Failed to undecline… Skipping approve.”
Güncelleme Expired/Superseded olabilir →
-SkipExpired -SkipSuperseded
.İç API çağrıları engellenmiş olabilir; bu durumda ilgili güncelleme konsoldan manuel olarak “decline kaldır” gerektirebilir.
3P kataloglarda (EXE/MSI özel paketler) metadata farklılıkları sorun çıkarabilir; başlık/ürün filtrelerini daraltıp tekrar deneyin.
10.3) “Argument type cannot be System.Void.”
Assembly yüklemede pipe kullanmayın:
$null = [Reflection.Assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
10.4) “Cannot validate argument on parameter 'ProductMatchMode'. The argument "False"
…”
"False"
…”Switch’leri
:$false
ile yazın:-AllowDecline:$false
.-AllowDecline $false
dersenizFalse
sonraki konumsal parametreye kayabilir.
11) Güvenlik & İdempotans
Fonksiyon, hedef grupta zaten Install onayı varsa tekrar approve etmez (idempotent).
Decline işlemleri geri alınabilir (undecline), fakat expired/superseded paketlerde geri getirmek anlamlı olmayabilir.
Her zaman yetkili bir WSUS hesabı ile çalışın; üretim ortamında DryRun ile test edin.
12) Hızlı Referans (Kısa Özet)
Yeni (>= Days) + filtrelere uyan → Approve (Install)
Eski (< Days) + filtrelere uyan +
-AllowDecline
→ DeclineRequiredFilter "op n"
→ NotInstalledCount’a karşı koşul-IncludeSubgroupsRequired
→ alt grupları dahil et-AutoUndeclineBeforeApprove:$true
→ Declined ise undecline + approve-SkipExpired -SkipSuperseded
→ bu tip güncellemeleri baştan atlaSayaçlar size “nerede elendiğini” gösterir.
13) Sürüm Notu (Bu belgeye göre)
PowerShell 5.1 uyumlu.
“Gerçek undecline” için Internal API cast + NonPublic reflection + “NotApproved fallback” sıralı yaklaşımı.
Ürün eşleşmesinde Exact/Like/Regex desteği.
Alt grupları Required sayımına dahil etme seçeneği.
Expired/Superseded atlama anahtarları.
14) Önerilen Komut Şablonları
Prod benzeri onay akışı:
Manage-WsusUpdates -Days 30 `
-Classifications @('Security Updates','Critical Updates') `
-RequiredFilter 'ge 1' `
-SkipExpired -SkipSuperseded `
-AllowDecline:$false `
-AutoUndeclineBeforeApprove:$true
Temizlik (eski & gereksiz) akışı:
Manage-WsusUpdates -Days 180 `
-RequiredFilter 'eq 0' `
-SkipExpired -SkipSuperseded `
-AllowDecline `
-AutoUndeclineBeforeApprove:$false
Hedef grup ve SSL ile örnek:
Manage-WsusUpdates -Days 365 `
-Products @('Tools','Documents') -ProductMatchMode Like `
-IncludeSubgroupsRequired -RequiredFilter 'gt 0' `
-SkipExpired -SkipSuperseded `
-TargetGroupName 'All Computers' `
-WsusServer 'arksup.arksoft.local' -UseSsl:$true -Port 8531 `
-AllowDecline:$false `
-AutoUndeclineBeforeApprove:$true
WSUS Export & Import PowerShell Script
function Invoke-WsusBackup {
param (
[ValidateSet("Export", "Import")]
[string]$Mode,
[string]$WsusToolsPath = "C:\Program Files\Update Services\Tools",
[string]$ContentSourcePath = "C:\WSUS\WsusContent",
[string]$UpdateServicesPackagesPath = "C:\WSUS\UpdateServicesPackages",
[string]$TargetFolder = "D:\WSUSBackup"
)
$logFile = Join-Path $TargetFolder "WsusBackup.log"
function Write-Log {
param ([string]$Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$entry = "$timestamp`t$Message"
Add-Content -Path $logFile -Value $entry
Write-Host $Message
}
function Export-Wsus {
$exportXml = Join-Path $TargetFolder "export.xml"
$exportLog = Join-Path $TargetFolder "export.log"
$contentTargetPath = Join-Path $TargetFolder "WsusContent"
$packagesTargetPath = Join-Path $TargetFolder "UpdateServicesPackages"
Write-Log "=== EXPORT STARTED ==="
if (!(Test-Path $TargetFolder)) {
New-Item -Path $TargetFolder -ItemType Directory | Out-Null
Write-Log "Backup folder created: $TargetFolder"
}
& "$WsusToolsPath\wsusutil.exe" export $exportXml $exportLog
Write-Log "Metadata export completed: $exportXml"
if (Test-Path $ContentSourcePath) {
robocopy $ContentSourcePath $contentTargetPath /MIR /ZB /NP /R:2 /W:5 >> $logFile
Write-Log "WsusContent copied to: $contentTargetPath"
}
if (Test-Path $UpdateServicesPackagesPath) {
robocopy $UpdateServicesPackagesPath $packagesTargetPath /MIR /ZB /NP /R:2 /W:5 >> $logFile
Write-Log "UpdateServicesPackages copied to: $packagesTargetPath"
}
Write-Log "=== EXPORT COMPLETED ==="
}
function Import-Wsus {
$exportXml = Join-Path $TargetFolder "export.xml"
$exportLog = Join-Path $TargetFolder "export.log"
$contentTargetPath = Join-Path $TargetFolder "WsusContent"
$packagesTargetPath = Join-Path $TargetFolder "UpdateServicesPackages"
Write-Log "=== IMPORT STARTED ==="
if (!(Test-Path $exportXml)) {
Write-Log "ERROR: Export XML not found: $exportXml"
return
}
& "$WsusToolsPath\wsusutil.exe" import $exportXml $exportLog
Write-Log "Metadata import completed"
if (Test-Path $contentTargetPath) {
robocopy $contentTargetPath $ContentSourcePath /MIR /ZB /NP /R:2 /W:5 >> $logFile
Write-Log "WsusContent restored to: $ContentSourcePath"
}
if (Test-Path $packagesTargetPath) {
robocopy $packagesTargetPath $UpdateServicesPackagesPath /MIR /ZB /NP /R:2 /W:5 >> $logFile
Write-Log "UpdateServicesPackages restored to: $UpdateServicesPackagesPath"
}
Write-Log "=== IMPORT COMPLETED ==="
}
switch ($Mode) {
"Export" { Export-Wsus }
"Import" { Import-Wsus }
default {
Write-Host "Usage examples:"
Write-Host " Invoke-WsusBackup -Mode Export -TargetFolder D:\WSUSBackup"
Write-Host " Invoke-WsusBackup -Mode Import -TargetFolder D:\WSUSBackup"
}
}
}
Bu PowerShell fonksiyonu, WSUS yapılandırmasını ve içeriklerini (örn. WsusContent
, UpdateServicesPackages
) dışa veya içe aktarmanı sağlar. Özellikle yedekleme ve offline taşıma senaryoları için uygundur.
Parametreler
-Mode
string
Zorunlu. "Export"
(Dışa Aktar) veya "Import"
(İçe Aktar) olmak zorundadır.
-WsusToolsPath
string
Opsiyonel. wsusutil.exe
dosyasının bulunduğu klasör. Varsayılan: C:\Program Files\Update Services\Tools
-ContentSourcePath
string
Opsiyonel. WsusContent
klasörünün bulunduğu veya kopyalanacağı yer. Varsayılan: C:\WSUS\WsusContent
-UpdateServicesPackagesPath
string
Opsiyonel. UpdateServicesPackages
klasörünün bulunduğu veya hedeflendiği dizin. Varsayılan: C:\WSUS\UpdateServicesPackages
-TargetFolder
string
Opsiyonel. Yedeklerin saklanacağı veya yedekten geri yükleneceği klasör. Varsayılan: D:\WSUSBackup
Usage
Örnek 1: WSUS verisini ve içeriğini dışa aktar (Export)
Invoke-WsusBackup -Mode Export
Metadata
D:\WSUSBackup\export.xml
olarak dışa aktarılırİçerik klasörleri (
WsusContent
,UpdateServicesPackages
) belirtilen hedefe kopyalanırLog dosyası oluşturulur:
D:\WSUSBackup\WsusBackup.log
Örnek 2: WSUS verisini ve içeriğini yedekten geri yükle (Import)
Invoke-WsusBackup -Mode Import
D:\WSUSBackup\export.xml
içinden metadata içe aktarılırİçerik dosyaları
C:\WSUS
altına kopyalanır
Örnek 3: Özel bir yedekleme klasörü ile kullan
Invoke-WsusBackup -Mode Export -TargetFolder "E:\Yedekler\WSUS2025"
Örnek 4: Özel WSUS kurulum dizinleri ile kullanım
Invoke-WsusBackup -Mode Export `
-WsusToolsPath "D:\WSUS\Tools" `
-ContentSourcePath "D:\WSUS\Data\Content" `
-UpdateServicesPackagesPath "D:\WSUS\Data\Packages" `
-TargetFolder "E:\Yedekler\WSUS_Full"
Oluşan Dosyalar ve Klasörler
export.xml
WSUS metadata (yapılandırma) yedeği
export.log
wsusutil
log dosyası
WsusContent\
Güncelleme içerik klasörü
UpdateServicesPackages\
Ek paket içerik klasörü
WsusBackup.log
Tüm işlemlere dair özel log dosyası
İpuçları
Yönetici olarak çalıştırmayı unutmayın.
Log dosyası sayesinde tüm işlemler takip edilebilir.
Offline WSUS kopyalama, test ortamına klonlama, veya felaket kurtarma senaryoları için idealdir.
Task Scheduler
ile otomatik zamanlama yapılabilir.
Last updated