معالجة الأخطاء

مكتمل

لقد رأيت حتى الآن كيف يمكن أن تؤدي إضافة المعلمات وبنيات التحكم في التدفق إلى جعل البرامج النصية مرنةً وأكثر أمانًا للاستخدام. ولكن في بعض الأحيان ستحصل على أخطاء في برامجك النصية. تحتاج إلى طريقة للتعامل مع تلك الأخطاء.

فيما يلي بعض العوامل التي يجب أخذها بعين الاعتبار:

  • كيفية التعامل مع الخطأ. في بعض الأحيان تحصل على أخطاء يمكنك استيرادها وأحيانا يكون من الأفضل إيقاف البرنامج النصي. من المهم التفكير في أنواع الأخطاء التي يمكن أن تحدث وكيفية إدارتها على أفضل وجه.

  • شكل الأخطاء الفادحة. هناك أنواع مختلفة من رسائل الخطأ. بعضها أشبه بتحذيرات للمستخدم أن شيئًا ما ليس على ما يرام. وبعضها أكثر حدة، ويحتاج المستخدم حقًا إلى الانتباه. يعتمد أسلوب معالجة الأخطاء على نوع الخطأ. يمكن أن يكون الأسلوب أي شيء بدءًا من تقديم رسالة إلى رفع مستوى الخطورة وإيقاف النص.

Errors

على سبيل المثال، قد يؤدي الأمر cmdlet أو الوظيفة إلى حدوث أنواع كثيرة من الأخطاء. نوصي بأن تكتب تعليمة برمجية لإدارة كل نوع من الأخطاء التي قد تحدث وأن تديرها على نحوٍ مناسب، بالنظر إلى النوع. على سبيل المثال، لنفترض أنك تحاول الكتابة إلى ملف. قد تحصل على أنواع مختلفة من الأخطاء، بناءً على ماهية الخطأ. إذا لم يُسمح لك بالكتابة إلى الملف، فقد تحصل على نوعٍ واحد من الأخطاء. إذا لم يكن الملف موجودًا، فقد تحصل على نوعٍ آخر من الأخطاء، وما إلى ذلك.

هناك نوعان من الأخطاء التي يمكنك الحصول عليها عندما تشغل PowerShell:

  • خطأ إنهاء. سيؤدي أي خطأ من هذا النوع إلى إيقاف التنفيذ في الصف الذي حدث فيه الخطأ. يمكنك معالجة هذا النوع من الأخطاء باستخدام إما Try-Catch أو Trap. في حالة عدم معالجة الخطأ، سيُنهى البرنامج النصي عند تلك النقطة ولن تُشغل أي عبارات.

    إشعار

    تقع البنية Trap خارج نطاق هذه الوحدة. إذا كنت مهتمًا، راجع نُبذة حول المقاطعة.

  • خطأ عدم الإنهاء. سيؤدي هذا النوع من الخطأ إلى إخطار المستخدم بوجود خطأ ما، لكن البرنامج النصي سيستمر. يمكنك ترقية هذا النوع من الأخطاء إلى خطأ إنهاء.

إدارة الأخطاء باستخدام Try/Catch/Finally

يمكنك التفكير في خطأ إنهاء باعتباره خطأ غير متوقع. هذه الأخطاء فادحة. عند التعامل مع أحد هذه الأخطاء، يجب أن تفكر في نوع من الخطأ وماذا يمكنك أن تفعل حياله.

هناك ثلاث بنيات ذات صلة يمكن أن تساعدك على إدارة هذا النوع من الخطأ:

  • Try. سوف تستخدم كتلة Try لتغليف عبارة واحدة أو أكثر. يمكنك وضع التعليمات البرمجية التي تريد تشغيلها — على سبيل المثال، التعليمات البرمجية التي تكتب إلى مصدر بيانات — داخل أقواس. من بين جميع Try، يجب أن يكون هناك Catch واحدة على الأقل أو كتلةFinally. إليك كيف تبدو:

    Try {
       # Statement. For example, call a command.
       # Another statement. For example, assign a variable.
    }
    
  • Catch. سوف تستخدام هذه الكلمة الأساسية من أجل catch خطأ أو manageعند حدوثه. تفحص بعد ذلك عنصر الاستثناء لفهم نوع الخطأ الذي حدث، ومكان حدوثه، وما إذا كان البرنامج النصي يمكنه الاسترداد. Catchيأتي مباشرةً بعد Try. يمكنك تضمين أكثر من واحدة Catch — واحدة لكل نوع من الأخطاء — إذا أردت. إليك مثال:

    Try {
       # Do something with a file.
    } Catch [System.IO.IOException] {
       Write-Host "Something went wrong"
    }  Catch {
       # Catch all. It's not an IOException but something else.
    }
    

    يحاول البرنامج النصي تشغيل أمر يؤدي بعض أعمال الإدخال/إخراج. Catch الأولى تكشف نوعًا معينًا من الأخطاء: [System.IO.IOException]. Catch الأخيرة تكشف أي شيء ليس [System.IO.IOException].

  • Finally. ستُشغل العبارات الموجودة في هذه الكتلة بغض النظر عما إذا كان هناك أي خطأ. ربما لن تستخدم هذه الكتلة كثيرًا، ولكنها قد تكون مفيدة لتنظيف الموارد، على سبيل المثال. لاستخدامها، أضفها باعتبارها الكتلة الأخيرة:

    Try {
       # Do something with a file.
    } Catch [System.IO.IOException] {
       Write-Host "Something went wrong"
    }  Catch {
       # Catch all. It's not an IOException but something else.
    } Finally {
       # Clean up resources.
    }
    

فحص الأخطاء

لقد تحدثنا عن عناصر الاستثناء في سياق اكتشاف الأخطاء. يمكنك استخدام هذه العناصر لفحص الخطأ الذي وقع واتخاذ الإجراءات المناسبة بشأنه. يحتوي عنصر الاستثناء على:

  • رسالة. تخبرك الرسالة في بضع كلمات بالخطأ الذي حدث.

  • تتبع المكدس. يخبرك تتبع المكدس بأي العبارات قد جرى تشغيلها قبل الخطأ. تخيل أن لديك استدعاءً للوظيفة A، متبوعًا بـ B، متبوعًا بـ C. يتوقف البرنامج النصي عن الاستجابة عند C. سيُظهر مكدس الذاكرة المؤقتة سلسلة الاستدعاء هذه.

  • الصف المخالف. يخبرك عنصر الاستثناء أيضًا بالصف الذي كان البرنامج النصي يشغله عند حدوث الخطأ. يمكن أن تساعدك هذه المعلومات على تصحيح تعليماتك البرمجية.

فكيف يمكنك فحص عنصر الاستثناء؟ هناك متغير مدمج، $_، والذي يحتوي على خاصية exception. للحصول على رسالة الخطأ، على سبيل المثال، يمكنك استخدام $_.exception.message. في التعليمات البرمجية، قد يبدو الأمر كما يلي:

Try {
     # Do something with a file.
   } Catch [System.IO.IOException] {
     Write-Host "Something IO went wrong: $($_.exception.message)"
   }  Catch {
     Write-Host "Something else went wrong: $($_.exception.message)"
   }

إثارة الأخطاء

في بعض الحالات، قد تحتاج إلى التسبب في حدوث خطأ:

  • أخطاء عدم الإنهاء. بالنسبة لهذا النوع من الأخطاء، تخطرك PowerShell فقط بحدوث خطأ ما، باستخدام الأمر Write-Error cmdlet، على سبيل المثال. يستمر تشغيل البرنامج النصي. قد لا يكون هذا هو السلوك الذي تريده. لرفع مستوى الخطورة، يمكنك استخدام معلمة مثل -ErrorAction للتسبب في خطأ يمكن اكتشافه مع Try/Catch، على هذا النحو:

    Try {
       Get-Content './file.txt' -ErrorAction Stop
    } Catch {
       Write-Error "File can't be found"
    }
    

    باستخدام المعلمة -ErrorAction والقيمة Stop، يمكنك أن تتسبب في حدوث خطأ يمكن اكتشافه Try/Catch.

  • قواعد العمل. قد يكون لديك حالة لا تتوقف فيها التعليمات البرمجية فعليًا عن الاستجابة، ولكنك ترغب فيها لأسباب تتعلق بالعمل. تخيل أنك تنظف الإدخال وتتحقق مما إذا كانت المعلمة مسارًا أم لا. قد يحدد أحد متطلبات العمل السماح بمسارات معينة فقط أو أن المسار يحتاج إلى أن يبدو بطريقة معينة. إذا فشلت عمليات الفحص، فمن المنطقي أن تطرح خطأ. في مثل هذه الحالة، يمكنك استخدام الكتلة Throw:

    Try {
       If ($Path -eq './forbidden') 
       {
         Throw "Path not allowed"
       }
       # Carry on.
    
    } Catch {
       Write-Error "$($_.exception.message)" # Path not allowed.
    }
    
    

    إشعار

    بوجهٍ عام، لا تستخدم Throw للتحقق من صحة المعلمة. استخدم سمات التحقق من الصحة بدلًا من ذلك. إذا لم تتمكن من جعل تعليماتك البرمجية تعمل مع هذه السمات، فإن Throw قد يكون خيارًا جيدًا.