Aracılığıyla paylaş


Özel durumlar hakkında bilmek istediğiniz her şey

Hata işleme, kod yazma söz konusu olduğunda hayatın yalnızca bir parçasıdır. Beklenen davranış için genellikle koşulları denetleyebiliriz ve doğrulayabiliriz. Beklenmeyen durum oluştuğunda özel durum işlemeye döneriz. Diğer kişilerin kodu tarafından oluşturulan özel durumları kolayca işleyebilir veya başkalarının işlemesi için kendi özel durumlarınızı oluşturabilirsiniz.

Uyarı

Bu makalenin özgün sürümü, @KevinMarquette tarafından yazılan blogda yer almıştır. PowerShell ekibi, bu içeriği bizimle paylaştığı için Kevin'e teşekkür ederiz. Lütfen PowerShellExplained.com'daki blogunu inceleyin.

Temel terminoloji

Bu terime geçmeden önce bazı temel terimleri ele almalıyız.

Exception

İstisna, normal hata yönetiminin sorunu çözemez durumda kaldığında oluşturulan bir olay gibidir. Bir sayıyı sıfıra bölmeye çalışmak veya yetersiz bellek, özel durum oluşturan bir şeye örnektir. Bazen kullandığınız kodun yazarı, bazı sorunlar oluştuğunda özel durumlar oluşturur.

Atma ve Yakalama

Bir özel durum oluştuğunda, bu özel durumun fırlatıldığı söylenir. Oluşan bir özel durumu işlemek için yakalamanız gerekir. İstisna fırlatılırsa ve herhangi bir şey tarafından yakalanmazsa betik çalışmayı durdurur.

Çağrı yığını

Çağrı yığını, birbirini çağıran işlevlerin listesidir. Bir işlev çağrıldığında, yığına veya listenin en üstüne eklenir. Fonksiyon çıktığında veya geri döndüğünde yığından kaldırılır.

Bir özel durum oluştuğunda, bir özel durum işleyicisi tarafından yakalanması için bu çağrı yığını denetlenir.

Sonlandırıcı ve sonlandırılmayan hatalar

İstisna genellikle sonlandırıcı bir hatadır. Fırlatılan bir istisna ya yakalanır ya da geçerli yürütmeyi sonlandırır. Varsayılan olarak, Write-Error sonlandırmayan bir hata oluşturur ve bir istisna fırlatmadan çıkış akışına bir hata ekler.

Bu durumu işaret ediyorum çünkü Write-Error ve diğer sonlandırılmayan hatalar catch'i tetiklemiyor.

Özel durum yutma

Bu, yalnızca bunu gizlemeye yönelik bir hata yakaladığınız zamandır. Sorunları gidermeyi çok zorlaştırabileceğinden bunu dikkatli bir şekilde yapın.

Temel komut söz dizimi

PowerShell'de kullanılan temel özel durum işleme söz dizimine hızlı bir genel bakış aşağıda verilmiştir.

Atmak

Özel bir durum olayı yaratmak için throw anahtar sözcüğüyle bir özel durum fırlatırız.

function Start-Something
{
    throw "Bad thing happened"
}

Bu, sonlandırıcı hata olan bir çalışma zamanı istisnası oluşturur. Çağıran fonksiyonda catch tarafından işlenir veya betikten şöyle bir iletiyle çıkar.

PS> Start-Something

Bad thing happened
At line:1 char:1
+ throw "Bad thing happened"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Bad thing happened:String) [], RuntimeException
    + FullyQualifiedErrorId : Bad thing happened

Write-Error -ErrorAction Durdurma

Bunun varsayılan olarak sonlandırıcı bir hata oluşturmadığından bahsettim Write-Error . belirtirseniz, -ErrorAction Stop, Write-Error ile işlenebilen bir sonlandırıcı hata oluşturur.

Write-Error -Message "Houston, we have a problem." -ErrorAction Stop

Lee Dailey'e -ErrorAction Stop bu şekilde kullanmayı hatırlattığınız için teşekkür ederim.

Cmdlet -ErrorAction Durdurma

Herhangi bir gelişmiş işlev veya cmdlet'te -ErrorAction Stop belirttiğinizde, tüm Write-Error deyimlerini yürütmeyi durduran veya catch tarafından işlenebilen sonlandırıcı hatalara dönüştürür.

Start-Something -ErrorAction Stop

ErrorAction parametresi hakkında daha fazla bilgi için bkz. about_CommonParameters. $ErrorActionPreference değişkeni hakkında daha fazla bilgi için bkz. about_Preference_Variables.

Deneyin/Yakalayın

Özel durum işlemenin PowerShell'de (ve diğer birçok dilde) çalışmasının yolu, önce try kodun bir bölümünü kullanmanız ve hata oluşturması durumunda bunu yapabilirsiniz catch . Aşağıda hızlı bir örnek verilmiştir.

try
{
    Start-Something
}
catch
{
    Write-Output "Something threw an exception"
    Write-Output $_
}

try
{
    Start-Something -ErrorAction Stop
}
catch
{
    Write-Output "Something threw an exception or used Write-Error"
    Write-Output $_
}

Betik catch yalnızca sonlandırıcı bir hata olduğunda çalışır. try doğru yürütülürse, catch üzerine atlar. catch bloğundaki özel durum bilgilerine, $_ değişkenini kullanarak erişebilirsiniz.

Deneyin/Son Olarak

Bazen bir hatayı işlemeniz gerekmez, ancak yine de bir özel durum oluşursa veya gerçekleşmezse yürütülecek bazı kodlar gerekir. Betik finally tam olarak bunu yapar.

Şu örneğe göz atın:

$command = [System.Data.SqlClient.SqlCommand]::new(queryString, connection)
$command.Connection.Open()
$command.ExecuteNonQuery()
$command.Connection.Close()

Bir kaynağı her açtığınızda veya kaynağa bağlandığınızda, kaynağı kapatmanız gerekir. ExecuteNonQuery() özel durum oluşturursa, bağlantı kapatılamaz. try/finally bloğun içinde aynı kod burada.

$command = [System.Data.SqlClient.SqlCommand]::new(queryString, connection)
try
{
    $command.Connection.Open()
    $command.ExecuteNonQuery()
}
finally
{
    $command.Connection.Close()
}

Bu örnekte, bir hata varsa bağlantı kapatılır. Hata yoksa da kapatılır. Script finally her çalıştırıldığında çalışır.

Özel durumu yakalamadığınız için, çağrı yığınında yukarıya doğru yayılmaya devam eder.

Deneyin/Yakalayın/Sonuçlandırın

catch ve finally birlikte kullanmak tamamen geçerlidir. Çoğu zaman birini veya diğerini kullanırsınız, ancak her ikisini de kullandığınız senaryolar bulabilirsiniz.

$PSItem

Temel bilgileri atlattığımıza göre, biraz daha derine inebiliriz.

Bloğun catch içinde, özel durumla ilgili ayrıntıları içeren türünde $PSItem bir otomatik değişken ($_ veya ErrorRecord) vardır. Bazı önemli özelliklere hızlı bir genel bakış aşağıda verilmiştir.

Bu örnekler için, bu özel durumu oluşturmak amacıyla ReadAllText içinde geçersiz bir yol kullandım.

[System.IO.File]::ReadAllText( '\\test\no\filefound.log')

PSItem.ToString()

Bu size günlükte ve genel çıktıda kullanmak için en temiz iletiyi verir. ToString() bir dizenin içine yerleştirilirse $PSItem otomatik olarak çağrılır.

catch
{
    Write-Output "Ran into an issue: $($PSItem.ToString())"
}

catch
{
    Write-Output "Ran into an issue: $PSItem"
}

$PSItem.InvocationInfo

Bu özellik, hatanın atıldığı işlev veya betik hakkında PowerShell tarafından toplanan ek bilgileri içerir. İşte oluşturduğum örnek özel durumdan InvocationInfo.

PS> $PSItem.InvocationInfo | Format-List *

MyCommand             : Get-Resource
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 5
OffsetInLine          : 5
ScriptName            : C:\blog\throwerror.ps1
Line                  :     Get-Resource
PositionMessage       : At C:\blog\throwerror.ps1:5 char:5
                        +     Get-Resource
                        +     ~~~~~~~~~~~~
PSScriptRoot          : C:\blog
PSCommandPath         : C:\blog\throwerror.ps1
InvocationName        : Get-Resource

Buradaki önemli ayrıntılar, ScriptName kodun Lineve çağrının ScriptLineNumber nerede başladığını gösterir.

$PSItem.ScriptStackTrace

Bu özellik, özel durumun oluşturulduğu koda sizi getiren işlev çağrılarının sırasını gösterir.

PS> $PSItem.ScriptStackTrace
at Get-Resource, C:\blog\throwerror.ps1: line 13
at Start-Something, C:\blog\throwerror.ps1: line 5
at <ScriptBlock>, C:\blog\throwerror.ps1: line 18

Yalnızca aynı betikteki işlevlere çağrı yapıyorum, ancak birden çok betik söz konusuysa bu çağrıları izler.

$PSItem.Exception

Oluşan gerçek istisna budur.

$PSItem.Exception.Message

Bu, özel durumu açıklayan ve sorun giderme sırasında iyi bir başlangıç noktası olan genel iletidir. Özel durumların çoğu varsayılan bir mesaja sahiptir, ancak bu mesaj, özel durum fırlatıldığında kullanıcı tarafından özel bir mesajla değiştirilebilir.

PS> $PSItem.Exception.Message

Exception calling "ReadAllText" with "1" argument(s): "The network path was not found."

Bu, ErrorRecord üzerinde bir ayar yapılmadığında $PSItem.ToString() çağrıldığında döndürülen iletidir.

$PSItem.Exception.InnerException

Özel durumlar iç özel durumlar içerebilir. Genellikle, çağırdığınız kod bir istisna yakalar ve farklı bir istisna fırlatırsa bu durum yaşanır. Özgün özel durum, yeni özel durumun içine yerleştirilir.

PS> $PSItem.Exception.InnerExceptionMessage
The network path was not found.

Bunu, istisnaları yeniden fırlatma konusunu ele aldığımda tekrar ele alacağım.

$PSItem.Exception.StackTrace

Bu, istisna için StackTrace’dir. Yukarıda bir ScriptStackTrace gösterdim, ancak bu seferki yönetilen koda yapılan çağrılar için.

at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean
 useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs,
 String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32
 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean
 checkHost)
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks,
 Int32 bufferSize, Boolean checkHost)
at System.IO.File.InternalReadAllText(String path, Encoding encoding, Boolean checkHost)
at CallSite.Target(Closure , CallSite , Type , String )

Bu yığın izlemesini yalnızca olay yönetilen koddan oluşturulduğunda alırsınız. Bu örnekte görebildiğimiz tek şey bu şekilde bir .NET Framework işlevini doğrudan çağırıyorum. Genellikle bir yığın izleme sırasında, kodunuzun nerede durduğunu ve sistem çağrılarının nerede başladığını belirlemeye çalışırsınız.

İstisnalarla çalışma

Özel durumlar, temel söz dizimi ve özelliklerinden daha fazlasını barındırır.

Türlendirilmiş istisnaları yakalama

Yakaladığınız özel durumlar konusunda seçici olabilirsiniz. Özel durumların bir türü vardır ve yakalamak istediğiniz özel durum türünü belirtebilirsiniz.

try
{
    Start-Something -Path $path
}
catch [System.IO.FileNotFoundException]
{
    Write-Output "Could not find $path"
}
catch [System.IO.IOException]
{
        Write-Output "IO error with the file: $path"
}

Özel durum türü, özel durumunuzla eşleşen bir tane bulunana kadar her catch blok için denetlenir. Özel durumların diğer özel durumlardan devralabileceğini fark etmek önemlidir. Yukarıdaki örnekte, FileNotFoundException, IOException öğesinden devralınır. Yani eğer IOException ilk olsaydı, onun yerine çağrılırdı. Birden çok eşleşme olsa bile yalnızca bir catch bloğu çağrılır.

Eğer bir System.IO.PathTooLongException olsaydı, IOException eşleşirdi, ancak bir InsufficientMemoryException olsaydı, o zaman hiçbir şey onu yakalayamazdı ve yığın içinde yukarı doğru yayılırdı.

Aynı anda birden çok türü yakalama

Aynı catch deyimle birden çok özel durum türünü yakalamak mümkündür.

try
{
    Start-Something -Path $path -ErrorAction Stop
}
catch [System.IO.DirectoryNotFoundException],[System.IO.FileNotFoundException]
{
    Write-Output "The path or file was not found: [$path]"
}
catch [System.IO.IOException]
{
    Write-Output "IO error with the file: [$path]"
}

Bu eklemeyi önerdiğiniz için Redditor'a u/Sheppard_Ra teşekkür ederiz.

Belirtilen türde istisnalar fırlatma

PowerShell'de türü belirtilen özel durumlar fırlatabilirsiniz. Dizeyle çağırmak throw yerine:

throw "Could not find: $path"

Aşağıdaki gibi bir özel durum hızlandırıcısı kullanın:

throw [System.IO.FileNotFoundException] "Could not find: $path"

Ancak, bu şekilde yaptığınızda bir ileti belirtmeniz gerekir.

Atılacak bir istisnanın yeni bir örneğini de oluşturabilirsiniz. Sistemde tüm yerleşik özel durumlar için varsayılan iletiler olduğundan, bunu yaptığınızda ileti isteğe bağlıdır.

throw [System.IO.FileNotFoundException]::new()
throw [System.IO.FileNotFoundException]::new("Could not find path: $path")

PowerShell 5.0 veya üzerini kullanmıyorsanız eski New-Object yaklaşımı kullanmanız gerekir.

throw (New-Object -TypeName System.IO.FileNotFoundException )
throw (New-Object -TypeName System.IO.FileNotFoundException -ArgumentList "Could not find path: $path")

Belirli bir istisna kullanarak, siz (veya diğerleri) önceki bölümde belirtildiği gibi istisnayı türüne göre yakalayabilirsiniz.

Write-Error -Exception

Bu tür özel durumları Write-Error'ye ekleyebiliriz ve yine de catch özel durum türüne göre hataları ayırt edebiliriz. Aşağıdaki örneklerde Write-Error gibi kullanın:

# with normal message
Write-Error -Message "Could not find path: $path" -Exception ([System.IO.FileNotFoundException]::new()) -ErrorAction Stop

# With message inside new exception
Write-Error -Exception ([System.IO.FileNotFoundException]::new("Could not find path: $path")) -ErrorAction Stop

# Pre PS 5.0
Write-Error -Exception ([System.IO.FileNotFoundException]"Could not find path: $path") -ErrorAction Stop

Write-Error -Message "Could not find path: $path" -Exception (New-Object -TypeName System.IO.FileNotFoundException) -ErrorAction Stop

Ardından şu şekilde yakalayabiliriz:

catch [System.IO.FileNotFoundException]
{
    Write-Log $PSItem.ToString()
}

.NET özel durumlarının büyük listesi

Reddit r/PowerShell topluluğunun yardımıyla bu gönderiyi tamamlayacak yüzlerce .NET özel durumu içeren bir ana liste derledim.

İlk olarak bu listede durumuma uygun olabilecek özel durumlar için arama yaptım. Temel System ad alanında özel durumları kullanmayı denemelisiniz.

İstisnalar nesnelerdir

Çok fazla türlenmiş özel durum kullanmaya başlarsanız, bunların nesne olduğunu unutmayın. Farklı özel durumların farklı oluşturucuları ve özellikleri vardır. FileNotFoundException belgelerine System.IO.FileNotFoundException için bakarsak, bir mesaj ve dosya yolu geçirebileceğimizi görürüz.

[System.IO.FileNotFoundException]::new("Could not find file", $path)

Ve bu dosya yolunu açıklayan bir FileName özelliği vardır.

catch [System.IO.FileNotFoundException]
{
    Write-Output $PSItem.Exception.FileName
}

Diğer oluşturucular ve nesne özellikleri için .NET belgelerine başvurmalısınız.

Özel durumu yeniden fırlatma

Bloğunuzda catchthrow yapacağınız tek şey aynı özel durumu catch ise, bu yüzden yapmayın. Gerçekleştiğinde bir istisnayı ele almayı veya bir eylem gerçekleştirmeyi planlıyorsanız, yalnızca bu durumda istisna ile ilgili catch kullanmalısınız.

İstisna üzerinde bir eylem gerçekleştirmek, ancak sonraki işlemlerin bununla başa çıkabilmesi için istisnayı yeniden fırlatmak istediğiniz zamanlar vardır. Bir mesaj yazabilir veya sorunu keşfettiğimiz yere yakın bir yerde günlüğe kaydedebilir ve sorunu yığının daha üst seviyelerinde ele alabiliriz.

catch
{
    Write-Log $PSItem.ToString()
    throw $PSItem
}

İlginç bir şekilde, throw içinden catch çağrı yapabiliriz ve mevcut özel durumu yeniden fırlatır.

catch
{
    Write-Log $PSItem.ToString()
    throw
}

Kaynak betik ve satır numarası gibi özgün yürütme bilgilerini korumak için istisnayı yeniden atmak istiyoruz. Bu noktada yeni bir özel durum oluşturursak, özel durumun başladığı yeri gizler.

Yeni bir istisnayı yeniden fırlatma

Bir özel durum yakalarsanız ancak farklı bir özel durum oluşturmak istiyorsanız, özgün özel durumu yenisinin içine yerleştirmeniz gerekir. Bu, yığının alt kısmındaki birinin $PSItem.Exception.InnerException olarak erişmesine olanak tanır.

catch
{
    throw [System.MissingFieldException]::new('Could not access field',$PSItem.Exception)
}

$PSCmdlet.ThrowTerminatingError()

Ham istisnalar için throw kullanmakla ilgili sevmediğim tek şey, hata iletisinin throw deyimini işaret ederek sorunun o satırda olduğunu göstermesidir.

Unable to find the specified file.
At line:31 char:9
+         throw [System.IO.FileNotFoundException]::new()
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], FileNotFoundException
    + FullyQualifiedErrorId : Unable to find the specified file.

31. satırda çağırdığım throw yüzünden betiğimin bozuk olduğunu bana beyan eden hata iletisi, betiğinizin kullanıcılarının görmesi için kötü bir iletidir. Onlara yararlı bir şey söylemiyor.

Dexter Dhami bunu düzeltmek için kullanabileceğimi ThrowTerminatingError() belirtmiş.

$PSCmdlet.ThrowTerminatingError(
    [System.Management.Automation.ErrorRecord]::new(
        ([System.IO.FileNotFoundException]"Could not find $Path"),
        'My.ID',
        [System.Management.Automation.ErrorCategory]::OpenError,
        $MyObject
    )
)

Get-Resource adlı bir işlevin içinde ThrowTerminatingError() çağrıldıysa, göreceğimiz hata budur.

Get-Resource : Could not find C:\Program Files (x86)\Reference
Assemblies\Microsoft\Framework\.NETPortable\v4.6\System.IO.xml
At line:6 char:5
+     Get-Resource -Path $Path
+     ~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (:) [Get-Resource], FileNotFoundException
    + FullyQualifiedErrorId : My.ID,Get-Resource

Sorunun kaynağı olarak Get-Resource işlevine nasıl işaret ettiğini görüyor musunuz? Bu, kullanıcıya yararlı bir şey söyler.

$PSItem bir ErrorRecord olduğu için, ThrowTerminatingError bu yöntemi de yeniden atmak için kullanabiliriz.

catch
{
    $PSCmdlet.ThrowTerminatingError($PSItem)
}

Bu, hatanın kaynağını Cmdlet'e değiştirir ve işlevinizin iç öğelerini Cmdlet'inizin kullanıcılarından gizler.

Deneme, sonlandırıcı hatalar oluşturabilir.

Kirk Munro bazı özel durumların yalnızca bir try/catch blok içinde yürütülürken hataları sonlandırdığını belirtir. Bana verdiği ve sıfıra bölme çalışma zamanı özel durumu oluşturan örnek aşağıda verilmiştir.

function Start-Something { 1/(1-1) }

Ardından hatayı ürettiğini görmek ve mesajın çıktısını hala almak için bunu bu şekilde çağırın.

&{ Start-Something; Write-Output "We did it. Send Email" }

Ancak aynı kodu içine try/catchyerleştirerek başka bir şey olduğunu görürüz.

try
{
    &{ Start-Something; Write-Output "We did it. Send Email" }
}
catch
{
    Write-Output "Notify Admin to fix error and send email"
}

Hatanın sonlandırıcı bir hataya dönüştüğünü ve bu nedenle ilk iletinin çıkışının alınmadığını görüyoruz. Bu konuda sevmediğim şey, bu kodu bir işlev içinde kullanabileceğiniz ve birisi try/catch kullanıyorsa farklı davranmasıdır.

Ben bu sorunla kendim karşılaşmadım ancak farkında olunması gereken bir köşe durumu.

try/catch içinde $PSCmdlet.ThrowTerminatingError()

Bir nüans $PSCmdlet.ThrowTerminatingError() Cmdlet'inizde sonlandırıcı bir hata oluşturmasıdır, ancak Cmdlet'inizden ayrıldıktan sonra ölümcül olmayan bir hataya dönüşür. Bu, hatanın nasıl ele alınacağını belirleme sorumluluğunu, işlevinizi çağıran kişiye yükler. Bunu sonlandırıcı bir hata haline getirmek için -ErrorAction Stop kullanabilir veya bunu try{...}catch{...} içinde çağırabilirler.

Genel işlev şablonları

Kirk Munro ile yaptığım konuşmada son bir önemli nokta, onun tüm ileri düzey işlevlerinde her try{...}catch{...}, begin, process ve end bloğunun etrafına bir blok koymasıydı. Bu genel catch bloklarında, işlevlerinden çıkan tüm istisnalarla başa çıkmak için $PSCmdlet.ThrowTerminatingError($PSItem) kullanan tek bir satır bulunmaktadır.

function Start-Something
{
    [CmdletBinding()]
    param()

    process
    {
        try
        {
            ...
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError($PSItem)
        }
    }
}

Her şey işlevlerindeki bir try deyimde olduğundan, her şey tutarlı bir şekilde hareket eder. Bu, son kullanıcıya dahili kodu oluşturulan hatadan gizleyen temiz hatalar da verir.

Tuzak

İstisnaların belirli bir yönüne try/catch odaklandım. Ama bu işi bitirmeden önce bahsetmem gereken eski bir özellik var.

Bir trap, bu kapsamda gerçekleşen tüm özel durumları yakalamak için bir betik veya fonksiyona yerleştirilir. Bir özel durum oluştuğunda içindeki trap kod yürütülür ve normal kod devam eder. Birden çok istisna oluşursa, tuzak tekrar tekrar çağrılır.

trap
{
    Write-Log $PSItem.ToString()
}

throw [System.Exception]::new('first')
throw [System.Exception]::new('second')
throw [System.Exception]::new('third')

Kişisel olarak bu yaklaşımı hiç benimsemedim ancak, tüm özel durumları günlüğe kaydeden ve yine de çalışmaya devam eden yönetici veya kontrol betiklerinde bunun değerini görebiliyorum.

Kapanış açıklamaları

Betiklerinize uygun özel durum işleme eklemek, bunları daha kararlı hale getirmekle kalmaz, aynı zamanda bu özel durumlarla ilgili sorunları gidermenizi de kolaylaştırır.

Özel durum işleme hakkında konuşurken throw ana kavramı üzerine çok zaman harcadım. PowerShell ayrıca, throw kullanacağınız tüm durumları işleyen bir Write-Error verdi. Bu nedenle, bunu okuduktan sonra kullanmanız throw gerektiğini düşünmeyin.

Bu detayda özel durum işleme hakkında yazmaya zaman ayırdığıma göre, şimdi kodumda hata oluşturmak için Write-Error -Stop kullanmaya geçeceğim. Ayrıca Kirk'in tavsiyesine uyarak ThrowTerminatingError'yi her işlev için başvurulacak özel durum işleyicim yapacağım.