Posted in

AD Kullanıcı ve Mailbox isimlerinde çift boşluk karakteri sorunu için çözüm

Kurumsal ölçekte yapılan IT migration projeleri, teknik olarak son derece hassas ve detay gerektiren süreçlerdir. Özellikle Active Directory ve Exchange gibi kritik servislerin devreye alınması sırasında, sistem yöneticileri ve mühendisler genellikle otomasyon scriptleri ve toplu kullanıcı taşıma araçları kullanır. Bu sayede binlerce nesne kısa sürede yeni yapıya entegre edilebilir.

Ancak bu tür işlemlerde en sık karşılaşılan sorunlardan biri, veri kalitesi ile ilgili hatalardır. Bu yazıda, bu tip bir geçiş sırasında karşılaştığım ve ilk bakışta küçük gibi görünen ama sistemsel sorunlara yol açabilecek bir hatayı — “çift boşluk (double space) problemi”ni — ve bunun çözümünü sizlerle paylaşacağım.

Geçiş sürecinde yaklaşık 13.000 kullanıcı, otomatik scriptler aracılığıyla CSV/Excel dosyalarından alınarak Active Directory ortamına import edildi. Bu süreçte kullanılan script, dosyaları işlerken DisplayName, Name veya Mail gibi alanlardaki metinleri doğru şekilde parse edememiş ve bazı kullanıcıların isimlerinde çift boşluk karakteri bırakmış.

Örnek Hatalı Formatlar:

  • “Ahmet  Yılmaz”

  • “Mehmet Ali  Koç”

  • “Ayşe  Nur  Demir”

Bu durum özellikle:

  • Exchange Global Address List’te arama sorunlarına,

  • Outlook autocomplete kayıtlarında çakışmalara,

  • DisplayName’e bağlı filtreleme ve sıralama işlemlerinde tutarsızlıklara neden olabilmektedir.

 

PowerShell Script ile Çift Boşluk Temizliği

Bu problemi kalıcı olarak çözmek için basit ama etkili bir PowerShell script hazırlamıştım. Bu script, Active Directory üzerindeki tüm kullanıcıları tarar ve DisplayName alanında birden fazla boşluk karakteri varsa, bunları tek boşluğa düşürerek düzeltir. Hem log dosyasına hem de powershell ya da powershell_ise üzerinden çalıştırıyorsanız takip edebilmeniz için ekrana logları yazdırır.

Ad kullanıcıları veya mailbox üzerinden kullanım sağlayabilirsiniz.

<#
.Synopsis
DisplayName’lerdeki çift boşluğu teke düşürmek için yazılmış scriptir. Script kendi dizini içinde Log klasörü içine loglarını yazmaktadır.
Script default olarak ‘ListOnly’ mode olarak çalışmaktadır. Log incelemesinden sonra scripti -ListAndFix parametresi ile çalıştırabilirsiniz.
Kullanıcıları ad üzerinden ya da mailbox olan userlar şekklinde çekebilirsiniz.
Not: AdAccount şeklinde çektiğinizde krbtgt, SystemMailbox gibi hesapları filtrelemeyi unutmayınız.
.EXAMPLE
Get-SpaceChar -GetUserFrom ADAccount
Get-SpaceChar -GetUserFrom Mailbox
Get-SpaceChar -GetUserFrom ADAccount -ListAndFix
Get-SpaceChar -GetUserFrom Mailbox -ListAndFix
.Author
Mustafa Emre GÜL
#>

function write-log
{
Param(
[Parameter(Mandatory=$true)]
[string]
$message,
[Parameter(Mandatory=$true)]
[string]
$pathlog
)

$an = get-date -f dd.MM.yy*HH.mm.ss.fff
$logstring = “$an | $message” | Add-Content $pathlog
return $logstring
}

function Get-SpaceChar
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param
(
# Param1 help description
[Parameter(Mandatory=$false,
Position=0)]
[switch]$ListAndFix,
[Parameter(Mandatory=$true,
Position=1)]
[ValidateSet(“Mailbox”,”ADAccount”)]
$GetUserFrom
)

Begin
{
#######

$an = Get-Date -f dd.MM.yy-HH.mm.ss.fff
$scriptpath = Split-Path $psISE.CurrentFile.FullPath
$logpath = “$scriptpath\Log\Get-SpaceChar_$an.log”
write-log -message “script başlatıldı.” -pathlog $logpath

#######

try
{
if($PSBoundParameters[“GetUserFrom”] -eq “Mailbox”)
{
if (! (Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue) )
{
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
}

write-log “Posta Kutuları çekilmeye başlandı.” -pathlog $logpath
$mbxs = Get-Mailbox -ResultSize unlimited
write-log “Posta Kutuları çekildi.” -pathlog $logpath
}
if($PSBoundParameters[“GetUserFrom”] -eq “ADAccount”)
{
Import-Module ActiveDirectory

Write-Host “AD Kullanıcıları çekiliyor.”
write-log “AD kullanıcıları çekilecek.” $logpath
$mbxs = Get-ADUser -Filter * -Properties *
write-log “AD Userları başarıyla çekildi. Obje Sayısı: $($mbxs.Count)” $logpath
}
}
catch
{
Write-Host -ForegroundColor Red “ERR : Kullanıcılar çekilemedi. $($Error[0].Exception.Message)”
write-log “ERR : Kullanıcılar çekilemedi. $($Error[0].Exception.Message)” $logpath
return
}
}
Process
{
$spcount = 0
$changecount = 0
$unchangecount = 0

Write-Verbose -Message “-ListAndFix parametresi kontrol ediliyor.”
if($PSBoundParameters[“ListAndFix”])
{
Write-Verbose -Message “-ListAndFix parametresi ile çalıştırıldığından bulunan hatalar düzeltilecektir.”
foreach ($mbx in $mbxs)
{
if($mbx.DisplayName -ne $null)
{
$chararr = $mbx.displayname.ToCharArray()
foreach ($char in $chararr)
{
if($char -eq ” “)
{
$spcount++
}
}

# Write-Host “$($mbx.Displayname) için $spcount adet Space karakteri bulunmuştur.”

if($spcount -gt 1)
{
for ($i = 1; $i -lt $mbx.DisplayName.Length; $i++)
{
$nextindex = $i+1
if($mbx.DisplayName[$i] -eq ” ” -and $mbx.DisplayName[$nextindex] -eq ” “){
write-log “$($mbx.displayname) için çift boşluk bulunmuştur. Alias : $($mbx.alias)” -pathlog $logpath
Write-host -BackgroundColor Red “$(Get-Date -Format s) : işlem Yapılan Kullanıcı : $($mbx.DisplayName) – çift boşluk bulunmuştur.”
$newDisplayName = $($mbx.DisplayName.Remove($nextindex,1))
write-log “Yeni DisplayName $newDisplayName olacak şekilde set edilecek.” -pathlog $logpath
try{

write-log “Display Name değiştiriliyor. Kullanıcı: $($mbx.Alias) || OldValue: $($mbx.DisplayName) – NewValue: $newDisplayName” -pathlog $logpath
if($PSBoundParameters[“GetUserFrom”] -eq “ADAccount”)
{
Set-Aduser -Identity $mbx -DisplayName $newDisplayName -Confirm:$false
Write-log “İşlem Başarılı.” -pathlog $logpath
}
if($PSBoundParameters[“GetUserFrom”] -eq “Mailbox”)
{
Set-Mailbox -Identity $mbx -DisplayName $newDisplayName -Name $newDisplayName -ErrorAction STOP
Write-log “İşlem Başarılı.” -pathlog $logpath
}
write-log “Bir sonraki kullanıcıya geçiliyor” $logpath
$changecount++
}
catch{
Write-log “ERR – İşlem Başarısız. $($mbx.Alias) için DisplayName Değiştirilemedi. $($Error[0].Exception.Message) ” -pathlog $logpath
$unchangecount++
}
}
}
}

$spcount = 0
}
else
{
write-log “$($mbx.DistinguishedName) kullanıcısnın DisplayName attribute olmadığı için işlem yapılmadı.” $logpath
}
}

Write-log “$($mbxs.Count) adet mailbox üzerinde $changecount kişide çift boşluk bulunarak işlem yapılmıştır. $unchangecount kişide ise çift boşluk bulunmuş fakat değişim sağlanırken hata alınmıştır.” -pathlog $logpath
}
else
{
Write-Host -ForegroundColor Cyan “Şu anda ‘ListOnly’ mode olarak çalışmaktsınız. Düzenlemenin gerçekleşmesi için scripti -ListAndFix parametresi ile çalıştırın.”
foreach ($mbx in $mbxs)
{
if($mbx.DisplayName -ne $null)
{
$chararr = $mbx.displayname.ToCharArray()
foreach ($char in $chararr)
{
if($char -eq ” “)
{
$spcount++
}
}

if($spcount -gt 1)
{
for ($i = 1; $i -lt $mbx.DisplayName.Length; $i++)
{
$nextindex = $i+1
if($mbx.DisplayName[$i] -eq ” ” -and $mbx.DisplayName[$nextindex] -eq ” “){
write-log “$($mbx.displayname) için çift boşluk bulunmuştur. Alias : $($mbx.Alias)” -pathlog $logpath
$changecount++
}
}
}

$spcount = 0
}
else
{
write-log “$($mbx.DistinguishedName) kullanıcısnın DisplayName attribute olmadığı için işlem yapılmadı.” $logpath
}

}
Write-log “$($mbxs.Count) adet mailbox üzerinde $changecount kişide çift boşluk bulunmuştur.” -pathlog $logpath
}

}
End
{
Write-Host “Script tamamlanmıştır.”
write-log “Script Tamamlanmıştır.” -pathlog $logpath
}
}

Faydalı olması dileğiyle…

Leave a Reply

Your email address will not be published. Required fields are marked *