Hayaletin Çırağı
Hayaletin Çırağı "Hayaletin Çırağı" (The Spook's Apprentice/The Last App...
 
        Modern iş dünyasında, uzaktan çalışma ve sanal masaüstü altyapıları (VDI) artık bir lüks değil, bir zorunluluk haline geldi. Ancak geleneksel VDI çözümlerinde kullanıcı profilleri, oturum açma süreleri ve uygulama performansı konusunda sıkıntılar yaşanabiliyordu. İşte tam bu noktada **FSLogix** devreye giriyor.
Peki, nedir bu FSLogix ve neden özellikle Microsoft'un bulut tabanlı sanal masaüstü hizmeti Windows 365 (Cloud PC) ve Azure Virtual Desktop (AVD) için bu kadar kritik bir rol oynuyor? Gelin, bu güçlü teknolojiyi her yönüyle inceleyelim.
FSLogix, başlangıçta bağımsız bir şirket olarak, VDI dünyasındaki en inatçı sorunlardan biri olan kullanıcı profili yönetimini çözmek için kuruldu. 2018 yılında Microsoft tarafından satın alınması, teknolojinin ne kadar değerli olduğunun bir göstergesiydi. Bu satın almanın ardından Microsoft, FSLogix'i **Azure Virtual Desktop** ve **Windows 365** müşterileri için **ücretsiz** olarak sunmaya başladı. Artık FSLogix, modern Microsoft bulut masaüstü ekosisteminin ayrılmaz ve standart bir parçası haline geldi.
**FSLogix**, sanal masaüstü ortamlarında kullanıcı deneyimini kökten iyileştiren bir **profil konteynerleme çözümüdür**. Temel amacı, kullanıcının profilini (masaüstü, belgeler, uygulama ayarları, geçici dosyalar vb.) uzak bir sunucuda barındırılan sanal bir sabit disk (.VHDX) dosyası içinde dinamik olarak taşımaktır.
Basit bir benzetme yapmak gerekirse: FSLogix, kullanıcıya özel her şeyi (kişiselleştirilmiş ofis düzeniniz, tarayıcı yer imleriniz, Outlook imzanız gibi) taşınabilir bir "bavul"a koyar. Hangi sanal bilgisayara (Cloud PC'ye) giderseniz gidin, bu bavul sizinle birlikte gelir ve her şey tanıdık geldiği gibi, anında hazır olur.
FSLogix'in değerini anlamak için, çözdüğü problemlere bakmak gerekir:
1. **Oturum Açma Sürelerinde Müthiş İyileşme**
Geleneksel profil çözümlerinde (UPD - UE-V gibi), kullanıcı oturum açtığında tüm profil dosyaları ağ üzerinden yüklenir. Bu, özellikle büyük profillere sahip kullanıcılar için uzun dakikalar sürebilir. FSLogix'te ise profil bir VHDX dosyası olarak saklanır ve oturum açma sırasında bu dosya, kullanıcının sanal makinesine sanal bir disk olarak bağlanır. Veri transferi değil, bağlama işlemi olduğu için oturum açma süreleri **saniyeler** seviyesine iner.
2. **Performans ve Uyumluluk**
Bazı uygulamalar (özellikle Microsoft Office, OneDrive ve tarayıcılar) profil içinde sürekli okuma/yazma işlemi yapar. Geleneksel yöntemlerde bu, ağ gecikmesi ve yüküne neden olur, uygulamalar yavaşlar hatta çöker. FSLogix, profili yerel bir disk gibi bağladığı için uygulamalar, sanki fiziksel bir bilgisayarda çalışıyormuş gibi yüksek performansla çalışır. Bu, **Office 365** performansı için özellikle hayati öneme sahiptir.
3. **Profil Bütünlüğü ve Güvenilirlik**
Geleneksel yöntemlerde profil kilitlenmeleri ve bozulmaları sık yaşanırdı. FSLogix'in konteyner yapısı, profilin tutarlı ve sağlam kalmasını sağlar, veri kaybı riskini en aza indirir.
4. **Daha Kolay Yönetim**
BT yöneticileri için profil boyut sınırlaması, disk yönetimi ve yedekleme stratejileri oluşturmak çok daha kolay hale gelir.
FSLogix çözümü birkaç temel bileşenden oluşur:
*   **FSLogix Apps**: Ana uygulamadır. Profil konteynerlerini yönetir.
*   **FSLogix Cloud Cache**: Profilin birden fazla konumda (örneğin, iki farklı Azure Depolama Alanı) eşzamanlı olarak tutulmasını sağlar. Bu, yüksek kullanılabilirlik (High Availability) sunar; bir depolama alanı erişilemez olsa bile kullanıcı oturum açmaya devam edebilir.
*   **Office Container**: Özellikle Outlook verilerini (OST dosyası) ayrı bir konteynerde saklayarak performansı daha da artırmak ve profil boyutunu kontrol altında tutmak için kullanılır.
*   **Application Masking (Uygulama Maskeleme)**: Kullanıcılara veya gruplara göre hangi uygulamaların görüneceğini dinamik olarak yönetmeye yarar.
*   **Azure Virtual Desktop (AVD)**
*   **Windows 365 (Cloud PC)**
*   **VMware Horizon**
*   **Citrix Virtual Apps and Desktops**
FSLogix, sanal masaüstü deneyimini "sorunlu" olmaktan çıkarıp "kusursuz" bir hale getiren bir teknolojidir. Kullanıcı memnuniyetini artırır, BT departmanının iş yükünü hafifletir ve bulut maliyetlerinin öngörülebilir olmasına yardımcı olur. Özellikle Microsoft ekosisteminde çalışıyorsanız ve AVD/Windows 365 kullanıyorsanız, FSLogix artık olmazsa olmaz, standart bir yapı taşıdır.
Kısacası, FSLogix, VDI dünyasında uzun süredir aranan "**kesintisiz, hızlı ve kişiselleştirilmiş kullanıcı deneyimi**"nin anahtarını sunuyor.
---
**Not:** Bu blog yazısı, FSLogix'in temel konseptlerini açıklamak için hazırlanmıştır. Ürün yapılandırması ve lisanslama detayları için her zaman resmi [Microsoft FSLogix dokümantasyonunu](https://docs.microsoft.com/en-us/fslogix/) kontrol etmeniz önerilir.
Tüm RDS sunucularında çalıştırın
Requires -RunAsAdministrator
1. FSLogix İndir (En son sürüm için Microsoft sitesinden manuel indirin)
https://aka.ms/fslogix_download
# Değişkenler - BUNLARI KENDİ ORTAMINIZA GÖRE DEĞİŞTİRİN
$FSLogixInstaller = "C:\Temp\FSLogixAppsSetup.exe"$ProfileShare = "\\FileServer\FSLogixProfiles$"  # UNC path$VHDLocation = $ProfileShare
# 2. FSLogix KurulumuWrite-Host "FSLogix kuruluyor..." -ForegroundColor Greenif (Test-Path $FSLogixInstaller) {    Start-Process -FilePath $FSLogixInstaller -ArgumentList "/install /quiet /norestart" -Wait    Write-Host "FSLogix kuruldu!" -ForegroundColor Green} else {    Write-Host "HATA: FSLogix installer bulunamadı: $FSLogixInstaller" -ForegroundColor Red    Write-Host "Lütfen https://aka.ms/fslogix_download adresinden indirin" -ForegroundColor Yellow    exit}
# 3. Registry AyarlarıWrite-Host "Registry ayarları yapılıyor..." -ForegroundColor Green
$RegPath = "HKLM:\SOFTWARE\FSLogix\Profiles"
# Registry path oluşturif (!(Test-Path $RegPath)) {    New-Item -Path $RegPath -Force | Out-Null}
# Temel AyarlarSet-ItemProperty -Path $RegPath -Name "Enabled" -Value 1 -Type DWordSet-ItemProperty -Path $RegPath -Name "VHDLocations" -Value $VHDLocation -Type MultiString
# VHD AyarlarıSet-ItemProperty -Path $RegPath -Name "SizeInMBs" -Value 30000 -Type DWord  # 30GBSet-ItemProperty -Path $RegPath -Name "IsDynamic" -Value 1 -Type DWord  # Dynamic VHDSet-ItemProperty -Path $RegPath -Name "VolumeType" -Value "VHDX" -Type String
# Performans OptimizasyonlarıSet-ItemProperty -Path $RegPath -Name "FlipFlopProfileDirectoryName" -Value 1 -Type DWordSet-ItemProperty -Path $RegPath -Name "PreventLoginWithFailure" -Value 0 -Type DWord  # Profil yüklenemezse local profil kullanSet-ItemProperty -Path $RegPath -Name "PreventLoginWithTempProfile" -Value 0 -Type DWord
# Eşzamanlı Oturum AyarlarıSet-ItemProperty -Path $RegPath -Name "ConcurrentUserSessions" -Value 1 -Type DWord  # Aynı kullanıcı birden fazla oturum açabilir
# Silme Politikası (Opsiyonel)Set-ItemProperty -Path $RegPath -Name "DeleteLocalProfileWhenVHDShouldApply" -Value 1 -Type DWord
# Office 365 Container (Opsiyonel ama önerilen)$OfficeRegPath = "HKLM:\SOFTWARE\Policies\FSLogix\ODFC"if (!(Test-Path $OfficeRegPath)) {    New-Item -Path $OfficeRegPath -Force | Out-Null}
Set-ItemProperty -Path $OfficeRegPath -Name "Enabled" -Value 1 -Type DWordSet-ItemProperty -Path $OfficeRegPath -Name "VHDLocations" -Value $VHDLocation -Type MultiStringSet-ItemProperty -Path $OfficeRegPath -Name "SizeInMBs" -Value 30000 -Type DWordSet-ItemProperty -Path $OfficeRegPath -Name "IsDynamic" -Value 1 -Type DWordSet-ItemProperty -Path $OfficeRegPath -Name "VolumeType" -Value "VHDX" -Type String
Write-Host "Registry ayarları tamamlandı!" -ForegroundColor Green
# 4. FSLogix Servisini BaşlatWrite-Host "FSLogix servisleri başlatılıyor..." -ForegroundColor GreenStart-Service -Name "frxsvc" -ErrorAction SilentlyContinueStart-Service -Name "frxdrv" -ErrorAction SilentlyContinueStart-Service -Name "frxccds" -ErrorAction SilentlyContinue
Set-Service -Name "frxsvc" -StartupType AutomaticSet-Service -Name "frxdrv" -StartupType Automatic
# 5. Servisleri Kontrol EtWrite-Host "`nServis Durumları:" -ForegroundColor CyanGet-Service -Name "frx*" | Select-Object Name, Status, StartType | Format-Table
Write-Host "`nFSLogix kurulumu tamamlandı!" -ForegroundColor GreenWrite-Host "Lütfen sunucuyu yeniden başlatın ve bir kullanıcı ile test edin." -ForegroundColor Yellow
Dosya sunucusunda çalıştırın
Requires -RunAsAdministrator
# Değişkenler - BUNLARI DEĞİŞTİRİN$SharePath = "D:\FSLogixProfiles"  # Local disk path$ShareName = "FSLogixProfiles$"  # $ gizli paylaşım yapar$DomainName = "DOMAIN"  # Domain adınız$UsersGroup = "$DomainName\Domain Users"$AdminsGroup = "$DomainName\Domain Admins"
# 1. Klasör OluşturWrite-Host "Profil klasörü oluşturuluyor: $SharePath" -ForegroundColor Greenif (!(Test-Path $SharePath)) {    New-Item -Path $SharePath -ItemType Directory -Force | Out-Null}
# 2. SMB Paylaşımı Oluştur
Write-Host "SMB paylaşımı oluşturuluyor..." -ForegroundColor Green
# Mevcut paylaşımı kaldır (varsa)if (Get-SmbShare -Name $ShareName -ErrorAction SilentlyContinue) {    Remove-SmbShare -Name $ShareName -Force}
# Yeni paylaşım oluşturNew-SmbShare -Name $ShareName `    -Path $SharePath `    -FullAccess $AdminsGroup `    -ChangeAccess $UsersGroup `    -Description "FSLogix Profile Containers"
# SMB 3.0 AyarlarıSet-SmbShare -Name $ShareName -EncryptData $true -Force
# 3. NTFS İzinleriWrite-Host "NTFS izinleri ayarlanıyor..." -ForegroundColor Green
# Mevcut izinleri temizle$Acl = Get-Acl $SharePath$Acl.SetAccessRuleProtection($true, $false)  # Inheritance'ı kapat
# Yeni izinler ekle$AdminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(    $AdminsGroup, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$UsersRule = New-Object System.Security.AccessControl.FileSystemAccessRule(    $UsersGroup, "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")
$SystemRule = New-Object System.Security.AccessControl.FileSystemAccessRule(    "SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
# Creator Owner - Kullanıcılar kendi klasörlerinde tam yetki$CreatorRule = New-Object System.Security.AccessControl.FileSystemAccessRule(    "CREATOR OWNER", "FullControl", "ContainerInherit,ObjectInherit", "InheritOnly", "Allow")
$Acl.SetAccessRule($AdminRule)$Acl.SetAccessRule($UsersRule)$Acl.SetAccessRule($SystemRule)$Acl.AddAccessRule($CreatorRule)
Set-Acl -Path $SharePath -AclObject $Acl
# 4. Quota Ayarları (Opsiyonel)Write-Host "Quota ayarları yapılıyor..." -ForegroundColor Green
# File Server Resource Manager gerekli$FSRM = Get-WindowsFeature -Name FS-Resource-Managerif (!$FSRM.Installed) {    Write-Host "File Server Resource Manager kuruluyor..." -ForegroundColor Yellow    Install-WindowsFeature -Name FS-Resource-Manager -IncludeManagementTools}
# Her kullanıcı için 50GB quotaNew-FSRMQuota -Path $SharePath -Template "50 GB Limit" -ErrorAction SilentlyContinue
# 5. BilgilendirmeWrite-Host "`n=== Yapılandırma Tamamlandı ===" -ForegroundColor GreenWrite-Host "Paylaşım UNC Path: \\$env:COMPUTERNAME\$ShareName" -ForegroundColor CyanWrite-Host "Local Path: $SharePath" -ForegroundColor Cyan
Write-Host "`nÖnemli Notlar:" -ForegroundColor YellowWrite-Host "1. Bu UNC path'i RDS sunucularındaki FSLogix ayarlarına ekleyin"Write-Host "2. RDS sunucularının bu paylaşıma erişebildiğinden emin olun"Write-Host "3. Antivirus exclusion ekleyin: $SharePath\*.vhd* "Write-Host "4. Backup planı yapın (VSS snapshot önerilir)"
# 6. TestWrite-Host "`nPaylaşım Testi:" -ForegroundColor CyanGet-SmbShare -Name $ShareName | Format-ListGet-SmbShareAccess -Name $ShareName | Format-Table
C:\Program Files\FSLogix\Apps\ içindeki .admx ve .adml dosyaları   \\domain.com\SYSVOL\domain.com\Policies\PolicyDefinitions\.admx dosyaları → root klasöre.adml dosyaları → en-US\ alt klasörüneFSLogix Profile ContainersKonum: Computer Configuration → Policies → Administrative Templates → FSLogix → Profile Containers
| Ayar | Değer | Açıklama | 
|---|---|---|
| Enabled | Enabled | FSLogix'i aktif et | 
| VHD Location | \\FileServer\FSLogixProfiles$ | Profil paylaşımı | 
| Size in MBs | 30000 | 30GB boyut | 
| Is Dynamic | Enabled | Dynamic VHD (alan tasarrufu) | 
| Volume Type | VHDX | Modern format | 
| Prevent login with failure | Disabled | Hata durumunda local profil kullan | 
| Prevent login with temp profile | Disabled | Temp profil izin ver | 
| Delete local profile | Enabled | VHD yüklendiğinde local profili sil | 
Konum: Computer Configuration → Policies → Administrative Templates → FSLogix → ODFC Containers
| Ayar | Değer | Açıklama | 
|---|---|---|
| Enabled | Enabled | Office Container aktif | 
| VHD Location | \\FileServer\FSLogixProfiles$ | Aynı paylaşım | 
| Size in MBs | 30000 | 30GB | 
| Is Dynamic | Enabled | Dynamic VHD | 
| Include Office Activation | Enabled | Office lisansını sakla | 
| Ayar | Değer | Açıklama | 
|---|---|---|
| Flip Flop Profile Directory Name | Enabled | SID yerine Username kullan | 
| Concurrent User Sessions | Enabled | Aynı kullanıcı birden fazla session | 
| Profile Type | 0 | Normal profile (0=Normal, 1=Try for read-write, 2=Read-only) | 
| Locked Retry Count | 3 | VHD kilitliyse deneme sayısı | 
| Locked Retry Interval | 15 | Denemeler arası bekleme (saniye) | 
Konum: User Configuration → Policies → Windows Settings → Folder Redirection
\\FileServer\Redirected$\%USERNAME%\Desktop\\FileServer\Redirected$\%USERNAME%\Documents\\FileServer\Redirected$\%USERNAME%\DownloadsNot: FSLogix kullanıyorsanız folder redirection'a genelde gerek yok!
Konum: Computer Configuration → Preferences → Control Panel Settings → Scheduled Tasks
Task Name: FSLogix-Cleanup-Old-Profiles
Trigger: Daily at 2:00 AM
Action: PowerShell Script
Script: Remove-Item "\\FileServer\FSLogixProfiles$\*" -Recurse -Force 
        -Include @('*.vhd','*.vhdx') 
        | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-90)}Konum: Computer Configuration → Policies → Administrative Templates → Windows Defender
\\FileServer\FSLogixProfiles$\*.vhd\\FileServer\FSLogixProfiles$\*.vhdxC:\Program Files\FSLogix\Apps\*gpupdate /force   # FSLogix log'larını kontrol et
   Get-Content "C:\ProgramData\FSLogix\Logs\Profile\*.log" -Tail 50
   
   # Profile container kontrol
   Test-Path "\\FileServer\FSLogixProfiles$\$env:USERNAME*"C:\ProgramData\FSLogix\Logs\Profile\C:\ProgramData\FSLogix\Logs\ODFC\1. VHD oluşturulmuyor:
2. Profile yüklenmiyor:
PreventLoginWithFailure = Disabled olmalı3. Yavaş login:
# Aktif FSLogix profilleri listele
Get-ChildItem "\\FileServer\FSLogixProfiles$" -Directory | 
Select-Object Name, 
@{N='Size(GB)';E={[math]::Round((Get-ChildItem $_.FullName -Recurse | 
Measure-Object -Property Length -Sum).Sum / 1GB, 2)}}, 
LastWriteTime | Sort-Object LastWriteTime -Descending
# FSLogix Monitoring ve Bakım Script
# Scheduled Task ile günlük çalıştırın
#Requires -RunAsAdministrator
# Değişkenler
$ProfileShare = "\\FileServer\FSLogixProfiles$"
$ReportPath = "C:\Reports\FSLogix"
$LogRetentionDays = 30
$OldProfileDays = 90
$EmailTo = "admin@domain.com"
$EmailFrom = "fslogix@domain.com"
$SMTPServer = "smtp.domain.com"
$SendEmail = $false  # Email göndermek için $true yapın
# Report klasörü oluştur
if (!(Test-Path $ReportPath)) {
    New-Item -Path $ReportPath -ItemType Directory -Force | Out-Null
}
$ReportFile = Join-Path $ReportPath "FSLogix-Report-$(Get-Date -Format 'yyyy-MM-dd').html"
# HTML Report başlat
$HTML = @"
    
    
    
    Tarih: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')
"@
# 1. FSLogix Servis Durumu
Write-Host "FSLogix servisleri kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
$Services = Get-Service -Name "frx*" -ErrorAction SilentlyContinue
foreach ($Service in $Services) {
    $StatusClass = if ($Service.Status -eq "Running") { "success" } else { "error" }
    $HTML += ""
}
$HTML += "| Servis | Durum | Startup Type | 
|---|---|---|
| $($Service.Name) | $($Service.Status) | $($Service.StartType) | 
"
# 2. Profil Paylaşım Kontrolü
Write-Host "Profil paylaşımı kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
if (Test-Path $ProfileShare) {
    $HTML += "✓ Paylaşım erişilebilir: $ProfileShare
"
    
    # Toplam profil sayısı ve boyutu
    $Profiles = Get-ChildItem -Path $ProfileShare -Directory -ErrorAction SilentlyContinue
    $TotalProfiles = $Profiles.Count
    
    $TotalSize = 0
    $ProfileDetails = @()
    
    foreach ($Profile in $Profiles) {
        $VHDs = Get-ChildItem -Path $Profile.FullName -Filter "*.vhd*" -ErrorAction SilentlyContinue
        foreach ($VHD in $VHDs) {
            $SizeGB = [math]::Round($VHD.Length / 1GB, 2)
            $TotalSize += $SizeGB
            $DaysOld = (New-TimeSpan -Start $VHD.LastWriteTime -End (Get-Date)).Days
            
            $ProfileDetails += [PSCustomObject]@{
                Username = $Profile.Name
                VHDFile = $VHD.Name
                SizeGB = $SizeGB
                LastAccess = $VHD.LastWriteTime
                DaysOld = $DaysOld
            }
        }
    }
    
    $HTML += ""
    
} else {
    $HTML += "✗ Paylaşım erişilemiyor: $ProfileShare
"
}
# 3. En Büyük Profiller (Top 10)
Write-Host "En büyük profiller listeleniyor..." -ForegroundColor Cyan
$HTML += ""
$TopProfiles = $ProfileDetails | Sort-Object SizeGB -Descending | Select-Object -First 10
foreach ($Profile in $TopProfiles) {
    $SizeClass = if ($Profile.SizeGB -gt 40) { "error" } elseif ($Profile.SizeGB -gt 30) { "warning" } else { "" }
    $HTML += ""
}
$HTML += "| Kullanıcı | VHD Dosyası | Boyut (GB) | Son Erişim | 
|---|---|---|---|
| $($Profile.Username) | $($Profile.VHDFile) | $($Profile.SizeGB) | $($Profile.LastAccess.ToString('dd.MM.yyyy HH:mm')) | 
"
# 4. Kullanılmayan Profiller (90+ gün)
Write-Host "Kullanılmayan profiller kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
$OldProfiles = $ProfileDetails | Where-Object { $_.DaysOld -gt $OldProfileDays } | Sort-Object DaysOld -Descending
if ($OldProfiles.Count -gt 0) {
    foreach ($Profile in $OldProfiles) {
        $HTML += ""
    }
    
    $OldProfileSize = ($OldProfiles | Measure-Object -Property SizeGB -Sum).Sum
    $HTML += "| Kullanıcı | VHD Dosyası | Boyut (GB) | Gün | Son Erişim | 
|---|---|---|---|---|
| $($Profile.Username) | $($Profile.VHDFile) | $($Profile.SizeGB) | $($Profile.DaysOld) | $($Profile.LastAccess.ToString('dd.MM.yyyy')) | 
⚠ $($OldProfiles.Count) kullanılmayan profil tespit edildi. Toplam: $([math]::Round($OldProfileSize, 2)) GB alan kazanılabilir.
"
} else {
    $HTML += "✓ Kullanılmayan profil yok.
"
}
# 5. Disk Alanı Kontrolü
Write-Host "Disk alanı kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
# Profil sunucusunun disk durumu
$Server = $ProfileShare.Split('\')[2]
$Disks = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $Server -Filter "DriveType=3" -ErrorAction SilentlyContinue
foreach ($Disk in $Disks) {
    $FreePercent = [math]::Round(($Disk.FreeSpace / $Disk.Size) * 100, 2)
    $FreeGB = [math]::Round($Disk.FreeSpace / 1GB, 2)
    $UsedGB = [math]::Round(($Disk.Size - $Disk.FreeSpace) / 1GB, 2)
    $TotalGB = [math]::Round($Disk.Size / 1GB, 2)
    
    $SpaceClass = if ($FreePercent -lt 10) { "error" } elseif ($FreePercent -lt 20) { "warning" } else { "success" }
    
    $HTML += ""
}
$HTML += "| Sunucu | Disk | Toplam (GB) | Kullanılan (GB) | Boş (GB) | Boş % | 
|---|---|---|---|---|---|
| $Server | $($Disk.DeviceID) | $TotalGB | $UsedGB | $FreeGB | $FreePercent% | 
"
# 6. FSLogix Event Log Hataları (Son 24 saat)
Write-Host "Event log hataları kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
$StartTime = (Get-Date).AddHours(-24)
$FSLogixErrors = Get-WinEvent -FilterHashtable @{
    LogName = 'Microsoft-FSLogix-Apps/Operational'
    Level = 2,3  # Error ve Warning
    StartTime = $StartTime
} -ErrorAction SilentlyContinue | Select-Object -First 20
if ($FSLogixErrors) {
    $HTML += ""
    foreach ($Error in $FSLogixErrors) {
        $LevelClass = if ($Error.LevelDisplayName -eq "Error") { "error" } else { "warning" }
        $HTML += ""
    }
    $HTML += "| Zaman | Level | Event ID | Mesaj | 
|---|---|---|---|
| $($Error.TimeCreated.ToString('dd.MM.yyyy HH:mm')) | $($Error.LevelDisplayName) | $($Error.Id) | $($Error.Message.Substring(0, [Math]::Min(100, $Error.Message.Length)))... | 
"
} else {
    $HTML += "✓ Son 24 saatte hata kaydı yok.
"
}
# 7. Aktif FSLogix Oturumları
Write-Host "Aktif oturumlar kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
# RDS sunucularını listele (ortamınıza göre değiştirin)
$RDSServers = @("RDS-Server1", "RDS-Server2")  # Değiştirin!
$ActiveSessions = @()
foreach ($Server in $RDSServers) {
    try {
        $Sessions = qwinsta /server:$Server 2>$null | Where-Object { $_ -match "Active" }
        foreach ($Session in $Sessions) {
            if ($Session -match '\s+(\w+)\s+(\w+)\s+(\d+)\s+Active') {
                $ActiveSessions += [PSCustomObject]@{
                    Server = $Server
                    Username = $matches[1]
                    Session = $matches[2]
                    ID = $matches[3]
                }
            }
        }
    } catch {
        Write-Host "Uyarı: $Server'a bağlanılamadı" -ForegroundColor Yellow
    }
}
if ($ActiveSessions.Count -gt 0) {
    $HTML += ""
    foreach ($Session in $ActiveSessions) {
        $HTML += ""
    }
    $HTML += "| Sunucu | Kullanıcı | Session | ID | 
|---|---|---|---|
| $($Session.Server) | $($Session.Username) | $($Session.Session) | $($Session.ID) | 
"
    $HTML += "Toplam Aktif Oturum: $($ActiveSessions.Count)
"
} else {
    $HTML += "Şu anda aktif oturum yok.
"
}
# 8. Otomatik Temizlik (Opsiyonel)
Write-Host "Eski profiller temizleniyor..." -ForegroundColor Cyan
$HTML += ""
$CleanupEnabled = $false  # Otomatik temizlik için $true yapın
$DeletedProfiles = @()
if ($CleanupEnabled -and $OldProfiles.Count -gt 0) {
    foreach ($Profile in $OldProfiles) {
        try {
            $VHDPath = Join-Path -Path $ProfileShare -ChildPath "$($Profile.Username)\$($Profile.VHDFile)"
            if (Test-Path $VHDPath) {
                Remove-Item -Path $VHDPath -Force -ErrorAction Stop
                $DeletedProfiles += $Profile
                Write-Host "Silindi: $VHDPath" -ForegroundColor Green
            }
        } catch {
            Write-Host "Hata: $VHDPath silinemedi - $_" -ForegroundColor Red
        }
    }
    
    if ($DeletedProfiles.Count -gt 0) {
        $FreedSpace = ($DeletedProfiles | Measure-Object -Property SizeGB -Sum).Sum
        $HTML += "✓ $($DeletedProfiles.Count) eski profil silindi. $([math]::Round($FreedSpace, 2)) GB alan kazanıldı.
"
    }
} else {
    $HTML += "Otomatik temizlik devre dışı. Aktif etmek için script'te \$CleanupEnabled = \$true yapın.
"
}
# 9. Registry Ayarları Kontrolü
Write-Host "Registry ayarları kontrol ediliyor..." -ForegroundColor Cyan
$HTML += ""
$RegPath = "HKLM:\SOFTWARE\FSLogix\Profiles"
$ExpectedSettings = @{
    "Enabled" = 1
    "VHDLocations" = $ProfileShare
    "IsDynamic" = 1
    "VolumeType" = "VHDX"
}
foreach ($Setting in $ExpectedSettings.GetEnumerator()) {
    try {
        $ActualValue = (Get-ItemProperty -Path $RegPath -Name $Setting.Key -ErrorAction Stop).$($Setting.Key)
        
        if ($Setting.Key -eq "VHDLocations") {
            $Match = $ActualValue -contains $Setting.Value
        } else {
            $Match = $ActualValue -eq $Setting.Value
        }
        
        $StatusClass = if ($Match) { "success" } else { "warning" }
        $Status = if ($Match) { "✓ OK" } else { "⚠ Farklı" }
        
        $HTML += ""
    } catch {
        $HTML += ""
    }
}
$HTML += "| Ayar | Değer | Durum | 
|---|---|---|
| $($Setting.Key) | $ActualValue | $Status | 
| $($Setting.Key) | - | ✗ Ayar bulunamadı | 
"
# 10. Öneriler
$HTML += ""
# HTML Sonlandır
$HTML += @"
    
    Bu rapor otomatik olarak oluşturulmuştur.
Script: FSLogix-Monitoring.ps1
Sunucu: $env:COMPUTERNAME
Oluşturma: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')
"@
# Raporu kaydet
$HTML | Out-File -FilePath $ReportFile -Encoding UTF8
Write-Host "`nRapor oluşturuldu: $ReportFile" -ForegroundColor Green
# Tarayıcıda aç
Start-Process $ReportFile
# Email gönder (opsiyonel)
if ($SendEmail) {
    try {
        $Subject = "FSLogix Monitoring Report - $(Get-Date -Format 'dd.MM.yyyy')"
        
        Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $Subject -Body $HTML -BodyAsHtml -SmtpServer $SMTPServer -Encoding UTF8
        
        Write-Host "Email gönderildi: $EmailTo" -ForegroundColor Green
    } catch {
        Write-Host "Email gönderilemedi: $_" -ForegroundColor Red
    }
}
# Eski raporları temizle
Write-Host "Eski raporlar temizleniyor..." -ForegroundColor Cyan
Get-ChildItem -Path $ReportPath -Filter "*.html" | 
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$LogRetentionDays) } | 
    Remove-Item -Force
Write-Host "`n=== İşlem Tamamlandı ===" -ForegroundColor Green
Dosya Sunucusunda Çalıştırın:
# Script: fslogix_fileserver.ps1
# Paylaşım oluştur
$SharePath = "D:\FSLogixProfiles"
$ShareName = "FSLogixProfiles$"
New-Item -Path $SharePath -ItemType Directory -Force
New-SmbShare -Name $ShareName -Path $SharePath -FullAccess "Domain Admins" -ChangeAccess "Domain Users"\\FileServer\FSLogixProfiles$Test-Path \\FileServer\FSLogixProfiles$ = TrueHer RDS Sunucusunda Çalıştırın:
# Script: fslogix_install.ps1
Start-Process -FilePath "C:\Temp\FSLogixAppsSetup.exe" -ArgumentList "/install /quiet /norestart" -WaitGet-Service frx*Her RDS Sunucusunda Çalıştırın:
# Script: fslogix_install.ps1 (Registry bölümü)Veya Group Policy ile yapılandırın (önerilen)
Enabled = 1VHDLocations = \\FileServer\FSLogixProfiles$SizeInMBs = 30000IsDynamic = 1VolumeType = VHDXTest kullanıcısı ile login olun:
\\FileServer\FSLogixProfiles$\username_SIDProfile_username.vhdxKontrol Komutları:
# Log kontrol
Get-Content "C:\ProgramData\FSLogix\Logs\Profile\*.log" -Tail 50
# VHD kontrol
Get-ChildItem "\\FileServer\FSLogixProfiles$" -Recurse -Filter "*.vhdx"
# Event log
Get-WinEvent -LogName 'Microsoft-FSLogix-Apps/Operational' -MaxEvents 20Aynı kullanıcı ile farklı RDS sunucusuna login olun:
Tüm RDS ve Dosya Sunucularında:
\\FileServer\FSLogixProfiles$\*.vhd*C:\Program Files\FSLogix\Apps\*C:\ProgramData\FSLogix\*✅ Login süresi <30 saniye
✅ Profil mount başarı oranı >99%
✅ Farklı sunucularda roaming çalışıyor
✅ Disk kullanımı planlandığı gibi
✅ Günde <5 hata event'i
✅ Login hızından şikayet yok
✅ Dosya kaybı yok
✅ Ayarlar korunuyor
✅ OneDrive/Teams sorunsuz
✅ Kullanıcılar farkında değil (en iyisi!)
C:\ProgramData\FSLogix\Logs\Profile\Applications and Services Logs → FSLogix