İstisnalar hakkında bilmek istediğiniz her şey


Kod yazma söz konusu olduğunda hata yönetimi hayatın bir parçasıdır. Beklenen davranışa ilişkin koşulları sıklıkla kontrol edip doğrulayabiliriz. Beklenmeyen bir durum meydana geldiğinde istisna yönetimine yöneliriz. Başkalarının kodları tarafından oluşturulan istisnaları kolayca halledebilir veya başkalarının işlemesi için kendi istisnalarınızı oluşturabilirsiniz.

Not

Bu makalenin orijinal versiyonu @KevinMarquette tarafından yazılan blogda yayınlandı. PowerShell ekibi bu içeriği bizimle paylaştığı için Kevin'e teşekkür ediyor. Lütfen PowerShellExplained.com adresindeki bloguna göz atın.

Temel terminoloji

Bu konuya geçmeden önce bazı temel terimleri ele almamız gerekiyor.

İstisna

İstisna, normal hata işlemenin sorunu çözemediği durumlarda oluşturulan bir olaya benzer. Bir sayıyı sıfıra bölmeye çalışmak veya hafızanın tükenmesi istisna yaratan bir şeye örnektir. Bazen kullandığınız kodun yazarı, belirli sorunlar meydana geldiğinde istisnalar oluşturabilir.

Fırlat ve Yakala

Bir istisna oluştuğunda, istisnanın atıldığını söyleriz. Atılan bir istisnayı ele almak için onu yakalamanız gerekir. Bir istisna atılırsa ve herhangi bir şey tarafından yakalanmazsa, betiğin yürütülmesi durdurulur.

Ç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 istisna atıldığında, bir istisna işleyicisinin onu yakalayabilmesi için bu çağrı yığını kontrol edilir.

Sonlandırılan ve sonlandırılmayan hatalar

Bir istisna genellikle bir sonlandırma hatasıdır. Atılan bir istisna ya yakalanır ya da mevcut yürütmeyi sonlandırır. Varsayılan olarak, Write-Error tarafından sonlandırılmayan bir hata oluşturulur ve bir istisna atmadan çıkış akışına bir hata ekler.

Bunu belirtiyorum çünkü Write-Error ve diğer sonlandırılmayan hatalar catch'ı tetiklemez.

Bir istisnayı yutmak

Bu, sırf onu bastırmak için bir hatayı yakaladığınız zamandır. Bunu dikkatli yapın çünkü sorun giderme sorunlarını çok zorlaştırabilir.

Temel komut sözdizimi

Burada PowerShell'de kullanılan temel istisna işleme sözdizimine hızlı bir genel bakış verilmiştir.

Fırlatmak

Kendi istisna olayımızı oluşturmak için throw anahtar sözcüğüyle bir istisna atarız.

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

Bu, sonlandırma hatası olan bir çalışma zamanı istisnası oluşturur. Çağıran bir işlevdeki catch tarafından yönetilir veya komut dosyasından buna benzer bir mesajla çı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 Stop

Write-Error'un varsayılan olarak sonlandırma hatası vermediğinden bahsetmiştim. -ErrorAction Stop belirtirseniz, Write-Error, catch ile işlenebilecek bir sonlandırma hatası oluşturur.

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

-ErrorAction Stop'un bu şekilde kullanılması gerektiğini hatırlattığı için Lee Dailey'e teşekkür ederiz.

Cmdlet -ErrorAction Durdurma

Herhangi bir gelişmiş işlev veya cmdlet'te -ErrorAction Stop belirtirseniz, tüm Write-Error deyimlerini, yürütmeyi durduran veya bir tarafından işlenebilen sonlandırma hatalarına dönüştürür. yakala.

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.

Dene/Yakala

PowerShell'de (ve diğer birçok dilde) istisna işlemenin çalışma şekli, önce kodun bir bölümünü denemeniz ve bir hata atarsa onu yakalayabilmenizdir. İşte hızlı bir örnek.

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 $_
}

catch betiği yalnızca bir sonlandırma hatası olduğunda çalışır. try doğru şekilde yürütülürse catch'in üzerinden atlanır. catch bloğundaki istisna bilgilerine $_ değişkenini kullanarak erişebilirsiniz.

Deneyin/Sonunda

Bazen bir hatayı işlemeniz gerekmez ancak bir istisna meydana gelse de gelmese de çalıştırmak için bazı kodlara ihtiyaç duyarsınız. Bir nihayet betiği tam olarak bunu yapar.

Bu örneğe bir 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 ona bağlandığınızda, onu kapatmalısınız. ExecuteNonQuery() bir istisna atarsa bağlantı kapatılmaz. Aynı kodu burada bir try/finally bloğunun içinde bulabilirsiniz.

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

Bu örnekte bir hata olması durumunda bağlantı kapatılır. Ayrıca herhangi bir hata yoksa kapatılır. nihayet betiği her zaman çalışır.

İstisnayı yakalayamadığınız için, bu durum yine de çağrı yığınına yayılır.

Dene/Yakala/Sonunda

catch ve finally'in birlikte kullanılması tamamen doğrudur. Çoğu zaman birini veya diğerini kullanırsınız, ancak her ikisini de kullandığınız senaryolar bulabilirsiniz.

$PSItem

Artık temelleri bir kenara bıraktığımıza göre, biraz daha derine inebiliriz.

catch bloğunun içinde, ErrorRecord türünde otomatik bir değişken ($PSItem veya $_) bulunur ve bu değişken şunları içerir: istisnayla ilgili ayrıntılar. Burada bazı önemli özelliklere hızlı bir genel bakış bulacaksınız.

Bu örneklerde, bu istisnayı oluşturmak için ReadAllText'te geçersiz bir yol kullandım.

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

PSItem.ToString()

Bu size günlük kaydında ve genel çıktıda kullanılacak en temiz mesajı verir. $PSItem bir dizenin içine yerleştirilirse ToString() otomatik olarak çağrılır.

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

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

$PSItem.InvokasyonInfo

Bu özellik, özel durumun oluşturulduğu işlev veya komut dosyası hakkında PowerShell tarafından toplanan ek bilgileri içerir. İşte oluşturduğum örnek istisnanın InvokasyonInfo'su.

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'i, kod Satırını ve çağrının başladığı ScriptLineNumber'u gösterir.

$PSItem.ScriptStackTrace

Bu özellik, sizi istisnanın oluşturulduğu koda yönlendiren 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ı komut dosyasındaki işlevlere çağrı yapıyorum ancak birden fazla komut dosyası söz konusuysa bu, çağrıları izler.

$PSItem.Exception

Bu, atılan gerçek istisnadır.

$PSItem.Exception.Message

Bu, istisnayı açıklayan genel mesajdır ve sorun giderme sırasında iyi bir başlangıç noktasıdır. Çoğu istisnanın varsayılan bir mesajı vardır ancak istisna atıldığında özel bir mesaja da ayarlanabilir.

PS> $PSItem.Exception.Message

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

Bu aynı zamanda ErrorRecord'da ayarlanmış bir ayar yoksa $PSItem.ToString() çağrılırken döndürülen mesajdır.

$PSItem.Exception.InnerException

İstisnalar iç istisnalar içerebilir. Bu genellikle aradığınız kodun bir istisna yakalayıp farklı bir istisna atması durumunda meydana gelir. Orijinal istisna, yeni istisnanın içine yerleştirilir.

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

İstisnaların yeniden atılması hakkında konuştuğumda buna daha sonra tekrar değineceğim.

$PSItem.Exception.StackTrace

Bu, istisnanın StackTrace'idir. Yukarıda bir ScriptStackTrace gösterdim, ancak bu, yönetilen koda yapılan çağrılar içindir.

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 izlemeyi yalnızca olay yönetilen koddan atıldığında alırsınız. Doğrudan bir .NET framework işlevini çağırıyorum, böylece bu örnekte görebildiğimiz tek şey bu. Genellikle bir yığın izlemesine baktığınızda kodunuzun nerede bittiğini ve sistem çağrılarının nerede başladığını ararsınız.

İstisnalarla çalışma

İstisnalarda temel söz dizimi ve istisna özelliklerinden daha fazlası vardır.

Yazılan istisnaları yakalamak

Yakaladığınız istisnalar dışında seçici olabilirsiniz. İstisnaların bir türü vardır ve yakalamak istediğiniz istisnanın 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"
}

İstisna türü, istisnanızla eşleşen bir tane bulunana kadar her catch bloğu için kontrol edilir. İstisnaların diğer istisnalardan miras alınabileceğinin farkına varmak önemlidir. Yukarıdaki örnekte FileNotFoundException, IOException'dan devralınır. Yani eğer IOException ilk olsaydı onun yerine çağrılacaktı. Birden fazla eşleşme olsa bile yalnızca bir catch bloğu çağrılır.

Bir System.IO.PathTooLongException'a sahip olsaydık, IOException eşleşirdi, ancak bir InsufficientMemoryException'a sahip olsaydık, onu hiçbir şey yakalayamaz ve yayılırdı yığını yukarı kaldırın.

Aynı anda birden fazla türü yakalayın

Aynı catch ifadesiyle birden fazla istisna 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ği için Reddit kullanıcısı u/Sheppard_Ra'ya teşekkür ederiz.

Yazılan istisnaları atma

PowerShell'de yazılı istisnalar oluşturabilirsiniz. throw'u bir dizeyle çağırmak yerine:

throw "Could not find: $path"

Bunun gibi bir istisna hızlandırıcı kullanın:

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

Ancak bu şekilde yaptığınızda bir mesaj belirtmeniz gerekiyor.

Ayrıca atılacak yeni bir istisna örneği de oluşturabilirsiniz. Sistemin tüm yerleşik istisnalar için varsayılan mesajları olduğundan, bunu yaptığınızda mesaj 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 üstünü kullanmıyorsanız eski New-Object yaklaşımını kullanmanız gerekir.

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

Yazılan bir istisna kullanarak, siz (veya başkaları) istisnayı önceki bölümde belirtildiği gibi türe göre yakalayabilirsiniz.

Yazma Hatası - İstisna

Yazılan bu istisnaları Write-Error'a ekleyebiliriz ve yine de hataları istisna türüne göre yakalayabiliriz. Aşağıdaki örneklerde olduğu gibi Write-Error 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

O zaman bunu şu şekilde yakalayabiliriz:

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

.NET istisnalarının büyük listesi

Bu gönderiyi tamamlamak için Reddit r/PowerShell topluluğunun yardımıyla yüzlerce .NET istisnası içeren bir ana liste derledim.

  • .NET istisnalarının büyük listesi

Durumuma uygun olacağını düşündüğüm istisnalar için bu listeyi arayarak başlıyorum. Temel System ad alanındaki istisnaları kullanmaya çalışmalısınız.

İstisnalar nesnelerdir

Çok sayıda yazılı istisna kullanmaya başlarsanız bunların nesne olduğunu unutmayın. Farklı istisnaların farklı yapıcıları ve özellikleri vardır. System.IO.FileNotFoundException için FileNotFoundException belgelerine bakarsak, bir mesaj ve dosya yolu iletebildiğimizi görürüz.

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

Ve bu dosya yolunu gösteren bir DosyaAdı özelliğine sahiptir.

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.

Bir istisnanın yeniden atılması

catch bloğunuzda yapacağınız tek şey aynı istisnayı atmak ise, onu catch yapmayın. Yalnızca ele almayı planladığınız bir istisnayı yakalamanız veya gerçekleştiğinde bir eylem gerçekleştirmeniz gerekir.

Bir istisna üzerinde bir eylem gerçekleştirmek istediğiniz ancak aşağı yöndeki bir şeyin bununla başa çıkabilmesi için istisnayı yeniden atmak istediğiniz zamanlar vardır. Bir mesaj yazabilir veya sorunu keşfettiğimiz yere yakın bir yere kaydedebiliriz, ancak sorunu yığının daha yukarılarında ele alabiliriz.

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

İlginçtir ki, catch içinden throw'u çağırabiliriz ve bu, geçerli istisnayı yeniden atar.

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

Kaynak komut dosyası ve satır numarası gibi orijinal yürütme bilgilerini korumak için istisnayı yeniden atmak istiyoruz. Bu noktada yeni bir istisna atarsak istisnanın başladığı yeri gizler.

Yeni bir istisnanın yeniden atılması

Bir istisna yakalarsanız ancak farklı bir istisna atmak istiyorsanız, orijinal istisnayı yeni istisnanın içine yerleştirmeniz gerekir. Bu, yığının alt kısmındaki birinin ona $PSItem.Exception.InnerException olarak erişmesine olanak tanır.

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

$PSCmdlet.ThrowTerfacingError()

Ham istisnalar için throw kullanmanın hoşuma gitmeyen yanı, hata mesajının throw deyimine işaret etmesi ve sorunun olduğu satırın o satır 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 throw dediğim için betiğimin bozulduğunu bildiren hata mesajının alınması, betiğinizin kullanıcılarının görmesi için kötü bir mesajdır. Onlara yararlı hiçbir şey söylemiyor.

Dexter Dhami bunu düzeltmek için ThrowTerfacingError()'u kullanabileceğimi belirtti.

$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 fonksiyonun içinde ThrowTerfacingError()'un çağrıldığını varsayarsak 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ğundan, yeniden atmak için ThrowTerfacingError'u da bu şekilde kullanabiliriz.

catch
{
    $PSCmdlet.ThrowTerminatingError($PSItem)
}

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

Deneyin sonlandırma hataları yaratabilir

Kirk Munro, bazı istisnaların yalnızca try/catch bloğu içinde yürütüldüğünde hataları sonlandırdığına dikkat çekiyor. İşte bana verdiği, sıfıra bölme çalışma zamanı istisnası oluşturan örnek.

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

Daha sonra hatayı oluşturduğunu ve yine de mesajın çıktısını aldığını görmek için onu bu şekilde çağırın.

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

Ancak aynı kodu bir try/catch içine yerleştirdiğimizde başka bir şeyin olduğunu görüyoruz.

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 hata haline geldiğini ve ilk mesajın çıktısını vermediğini görüyoruz. Bu konuda hoşuma gitmeyen şey, bu kodu bir fonksiyonda bulundurabilmeniz ve birisi try/catch kullanıyorsa farklı davranmasıdır.

Bununla ilgili herhangi bir sorunla karşılaşmadım ancak dikkat edilmesi gereken önemli bir durum.

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

$PSCmdlet.ThrowTerfacingError()'un bir nüansı, Cmdlet'iniz içinde bir sonlandırma hatası oluşturması, ancak Cmdlet'inizden ayrıldıktan sonra sonlanmayan bir hataya dönüşmesidir. Bu, hatanın nasıl ele alınacağına karar verme yükünü işlevinizi arayan kişiye bırakır. -ErrorAction Stop'u kullanarak veya onu bir try{...}catch{... içinden çağırarak bunu tekrar sonlandırıcı bir hataya dönüştürebilirler.

Genel işlev şablonları

Kirk Munro ile yaptığım konuşmada edindiğim son bir fikir, onun her başlangıç'ın etrafına bir dene{...}yakala{... yerleştirmesiydi, process ve end bloğunu tüm gelişmiş işlevlerinde kullanır. Bu genel yakalama bloklarında, işlevlerinden ayrılan tüm istisnalarla başa çıkmak için $PSCmdlet.ThrowTerfacingError($PSItem) kullanan tek bir satırı var.

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

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

İşlevleri içerisinde her şey bir try deyiminde olduğundan her şey tutarlı bir şekilde hareket eder. Bu aynı zamanda son kullanıcıya, dahili kodu oluşturulan hatadan gizleyen temiz hatalar verir.

Tuzak

İstisnaların dene/yakala yönüne odaklandım. Ancak bunu bitirmeden önce bahsetmem gereken eski bir özellik var.

Bir tuzak, o kapsamda meydana gelen tüm istisnaları yakalamak için bir komut dosyasına veya işleve yerleştirilir. Bir istisna meydana geldiğinde trap içindeki kod çalıştırılır ve ardından normal kod devam eder. Birden fazla istisna meydana gelirse 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çbir zaman benimsemedim, ancak tüm istisnaları günlüğe kaydeden ve ardından yürütmeye devam eden yönetici veya denetleyici komut dosyalarındaki değeri görebiliyorum.

Kapanış konuşmaları

Komut dosyalarınıza uygun istisna işleme eklemek, onları yalnızca daha kararlı hale getirmekle kalmaz, aynı zamanda bu istisnaları gidermenizi de kolaylaştırır.

throw hakkında konuşmaya çok zaman harcadım çünkü bu, istisna yönetimi hakkında konuşurken temel bir kavramdır. PowerShell ayrıca bize throw'u kullanacağınız tüm durumları ele alan Write-Error'u da verdi. O yüzden bunu okuduktan sonra throw kullanmanız gerektiğini düşünmeyin.

Artık bu ayrıntıda istisna yönetimi hakkında yazmaya zaman ayırdığıma göre, kodumda hatalar oluşturmak için Write-Error -Stop kullanımına geçeceğim. Ayrıca Kirk'ün tavsiyesine uyup ThrowTerfacingError'u her işlev için özel durum işleyicim yapacağım.

İlgili makaleler