الأنبوبة في باور شيل هي واحدة من أهم (وأكثرها فائدة) ميزات باور شيل ولغة البرمجة. بمجرد فهمك للأساسيات حول كيفية عملها وما يمكنها القيام به، يمكنك الاستفادة من قوتها في وظائفك الخاصة. في هذا البرنامج التعليمي، ستقوم بذلك بالضبط!
الأنبوبة في باور شيل تتيح لك ربط الأوامر معًا لبناء “أنبوبة” واحدة تبسيطًا للكود، وتمكين المعالجة المتوازية والمزيد. إذا كنت مستعدًا للتعرف على الأنبوبة وبناء وظائفك الخاصة للاستفادة من الأنبوبة، دعنا نبدأ!
المتطلبات المسبقة
سيكون هذا المنشور برنامجًا تعليميًا وستكون جميع العروض التوضيحية تطبيقية. إذا كنت ترغب في متابعة، ستحتاج إلى باور شيل v3+ . سيتم استخدام نافذة التعليمات البرمجية هذه في ويندوز PowerShell v5.1.
فهم أنبوبة باور شيل
معظم الأوامر في باور شيل تستقبل بعض الإدخال عبر معلمة. الأمر يتلقى بعض الكائن كإدخال ويقوم بشيء معين به داخليًا. ثم يُرجع اختياريًا بعض الكائن عبر الإخراج.
الأوامر في الأنبوبة تعمل مثل العدائين البشر في سباق التتابع. يقبل كل عداء في السباق، باستثناء الأول والأخير، العصا (الكائنات) من سابقه ويمررها إلى العداء التالي.
على سبيل المثال، يحتوي الـ Stop-Service
cmdlet على معامل يُسمى InputObject
. يسمح لك هذا المعامل بتمرير نوع محدد من الكائن إلى Stop-Service
الذي يُمثل خدمة Windows التي ترغب في إيقافها.
لاستخدام معامل InputObject
، يمكنك استرجاع كائن الخدمة عبر Get-Service
ومن ثم تمرير الكائن إلى معامل InputObject
كما هو موضح أدناه. هذا الأسلوب لتقديم الإدخال إلى cmdlet Stop-Service
عبر معامل InputObject
يعمل بشكل رائع وينجز المهمة.
هذا الأسلوب لتمرير الإدخال إلى أمر Stop-Service
يتطلب خطوتين متميزتين. يجب على PowerShell تشغيل Get-Service
أولاً ، وحفظ الناتج في متغير ، ثم تمرير تلك القيمة إلى Stop-Service
عبر معامل InputObject
.
الآن ، قارن الكود أعلاه مع الكود أدناه ، الذي يقوم بنفس العمل. إنه أبسط بكثير لأنه لا يتعين عليك إنشاء متغير $services
أو حتى استخدام معامل InputObject
على الإطلاق. بدلاً من ذلك ، يعرف PowerShell أنك تنوي استخدام معامل InputObject
. يفعل ذلك من خلال مفهوم يُسمى ربط المعاملات.
لقد قمت الآن بـ “ربط” الأوامر معًا باستخدام مشغل |
. لقد أنشأت pipeline.
ولكن ليس عليك استخدام فقط أمرين لإنشاء pipeline ؛ يمكنك ربط العديد منها معًا (إذا دعمت معاملات الأوامر ذلك). على سبيل المثال ، يعرض كود الأمثلة أدناه:
- يمرر جميع الكائنات التي يُرجعها أمر
Get-Service
إلى أمرWhere-Object
. - ينظر بعد ذلك أمر
Where-Object
إلى خاصيةStatus
لكل كائن ويُرجع فقط تلك الكائنات التي تحتوي على قيمةRunning
. - ثم، يتم إرسال كل من هذه الكائنات إلى أمر
Select-Object
، الذي يُرجع فقط خصائصName
وDisplayName
للكائنات. - نظرًا لعدم قبول أمر آخر الكائنات التي يُخرجها
Select-Object
، يتم إرجاع الأوامر مباشرةً إلى وحدة التحكم.
يفهم أمر
Where-Object
وSelect-Object
كيفية معالجة إدخال الأنابيب من خلال مفهوم يُسمى ربط المعلمة، والذي يتم مناقشته في القسم التالي.
لمزيد من المعلومات حول الأنابيب، قم بتشغيل الأمر
Get-Help about_pipelines
.
ربط معلمة الأنبوب
عند النظر الأول إلى الأنبوب، قد يبدو بسيطًا. بعد كل شيء، إنه مجرد تمرير الكائنات من أمر إلى آخر. ولكن في الواقع، الأنبوب أكثر تعقيدًا بكثير. تقبل الأوامر الإدخال عبر المعلمات فقط. يجب على الأنبوب بطريقة ما أن يحدد أي معلمة يجب استخدامها حتى عندما لا تقوم بتحديدها صراحة.
المهمة المتمثلة في معرفة أي معلمة يجب استخدامها عندما تتلقى الأمر إدخالًا عبر الأنبوبة تعرف باسم ربط المعلمة. لربط كائن قادم من الأنبوبة بمعلمة بنجاح، يجب أن تدعم معلمات الأمر الواردة هذا الأمر. تدعم معلمات الأمر ربط المعلمة بالأنبوبة بطريقة واحدة من طريقتين؛ ByValue
و/أو ByPropertyName
.
ByValue
تقبل معلمة الأمر كامل الكائن الوارد كقيمة للمعلمة. تبحث معلمة ByValue
عن كائن من نوع معين في الكائنات الواردة. إذا كان نوع الكائن هو مطابق، يفترض PowerShell أن الكائن معني بأن يكون مرتبطًا بتلك المعلمة ويقبله.
لديها الأمر
Get-ChildItem
معلمة تسمىPath
التي تقبل كائن نصي وإدخال أنبوبة عبرByValue
. وبسبب هذا، يُعيد تشغيل شيء مثل'C:\Windows' | Get-ChildItem
جميع الملفات في دليل C:\Windows لأنC:\Windows
هو سلسلة.
ByPropertyName
لا تقبل معلمة الأمر الكائن بأكمله ولكن خاصية واحدة من ذلك الكائن. تقوم بذلك ليس عن طريق النظر إلى نوع الكائن ولكن اسم الخاصية.
يحتوي أمر
Get-Process
على معلمةName
مُعدة لقبول إدخال الأنابيب بواسطة الخصائص. عند تمرير كائن يحتوي على خاصيةName
إلى أمرGet-Process
مثل[pscustomobject]@{Name='firefox'} | Get-Process
، يُطابق PowerShell أو يُرتبط بخاصيةName
في الكائن الوارد إلى معلمةName
ويستخدم تلك القيمة.
اكتشاف معلمات الأوامر التي تدعم الأنابيب
كما ذُكر سابقًا، لا تدعم كل أمر إدخال الأنابيب. يجب على مؤلف الأمر إنشاء تلك الوظيفة أثناء التطوير. يجب أن يحتوي الأمر على معلمة واحدة على الأقل تدعم الأنابيب، وتحديدًا ByValue
أو ByPropertyName
.
كيف تعرف أي الأوامر ومعلماتها تدعم إدخال الأنابيب؟ يمكنك مجرد تجربتها بالتجربة والخطأ، ولكن هناك طريقة أفضل باستخدام نظام مساعدة PowerShell باستخدام أمر Get-Help
.
على سبيل المثال، انظر إلى معلمة Path
لأمر Get-ChildItem
أدناه. يمكنك رؤية أنها تدعم كلاً من أنواع إدخال الأنابيب.

بمجرد معرفتك بالمعلمات التي تدعم إدخال الأنابيب، يمكنك ثم الاستفادة من تلك الوظيفة، كما هو موضح أدناه.
لكن، من ناحية أخرى، لا يدعم معلمة DisplayName
على Get-Service
إدخال الأنابيب.

بناء وظيفة أنبوب بنفسك
رغم أن المعالجات القياسية لـ PowerShell تدعم إدخال الأنابيب لا يعني ذلك أنه لا يمكنك الاستفادة من تلك الوظيفة. لحسن الحظ، يمكنك بناء وظائف تقبل إدخال الأنابيب أيضًا.
لتوضيح، دعنا نبدأ بوظيفة موجودة تسمى Get-ConnectionStatus
.
- تحتوي هذه الوظيفة على معلمة واحدة (لا تقبل إدخال الأنابيب) تسمى
ComputerName
، والتي تسمح لك بتمرير سلسلة واحدة أو أكثر إليها. يمكنك ملاحظة أن معلمةComputerName
لا تقبل إدخال الأنابيب لأنها لم تُعرف كسمة للمعلمة ([Parameter()]
). - ثم تقرأ الوظيفة كل واحدة من تلك السلاسل وتشغل معالج الأوامر
Test-Connection
ضد كل واحدة منها. - لكل اسم كمبيوتر مرر، يعيد ثم كائنًا يحتوي على خاصية
ComputerName
وخاصيةStatus
.
ثم يمكنك استدعاء Get-ConnectionStatus
عن طريق تمرير معلمة ComputerName
واحدة أو أكثر من أسماء المضيفين أو عناوين IP مثلما هو موضح أدناه.
الخطوة 1: السماح بإدخال من الأنبوبة
لتمكين هذه الوظيفة من قبول إدخال من الأنبوبة، يجب عليك أولاً تحديد السمة المناسبة للمعلمة. يمكن أن تكون هذه السمة إما ValueFromPipeline
لقبول الإدخال من الأنبوبة بالقيمة أو ValueFromPipelineByPropertyName
لقبول الإدخال من الأنبوبة بواسطة اسم الخاصية.
لهذا المثال، أضف سمة ValueFromPipeline
داخل القوسين لتعريف [Parameter()]
كما هو موضح أدناه.
في هذه النقطة، هذا كل ما عليك فعله من الناحية الفنية. وظيفة Get-ConnectionStatus
ستربط الآن أي كائن نصي يتم تمريره إليه بالمعلمة ComputerName
. ومع ذلك، حتى وإن كان ربط المعلمة يحدث لا يعني أن الوظيفة ستقوم بأي شيء ذو معنى معه.
الخطوة 2: إضافة كتلة عمل
عندما تريد باور شيل معالجة جميع الكائنات القادمة من الأنبوبة، يجب عليك إضافة كتلة Process
للتنفيذ. تخبر هذه الكتلة باور شيل بتنفيذ عملية كل كائن قادم من الأنبوبة.
بدون كتلة
Process
، سوف يقوم باور شيل فقط بمعالجة أول كائن قادم من الأنبوبة. تخبر كتلةProcess
باور شيل بمواصلة معالجة الكائنات.
يرجى إرسال الإخراج دائمًا من داخل كتلة
Process
. إرسال الإخراج من داخل كتلةProcess
يقوم بتيار الكائنات إلى الأنبوب مما يتيح للأوامر الأخرى قبول تلك الكائنات من الأنبوب.
تمرير الكائنات إلى أنبوب PowerShell
بمجرد تحديد كتلة Process
في الوظيفة أعلاه، يمكنك الآن استدعاء الوظيفة وتمرير القيم إلى معلمة ComputerName
عبر الأنبوب كما هو موضح أدناه.
في هذه النقطة، يمكنك الاستفادة من قوة الأنبوب الحقيقية وبدء دمج المزيد من الأوامر في المزيج. على سبيل المثال، ربما لديك ملف نصي، C:\Test\computers.txt، مع سطر من عناوين IP مفصولة عبر سطر جديد مثلما يلي.
ثم يمكنك استخدام cmdlet Get-Content
لقراءة كل من تلك العناوين IP في الملف النصي وتمريرها مباشرة إلى الوظيفة Get-ConnectionStatus
.
أخذ هذا الإعداد خطوة أبعد، يمكنك توجيه الكائنات التي تعيدها Get-ConnectionStatus
مباشرة إلى cmdlet ForEach-Object
.
الكود أدناه:
- يقوم بقراءة جميع أسماء الحواسيب في ملف النص ويمررها إلى وظيفة
Get-ConnectionStatus
. Get-ConnectionStatus
تعالج كل اسم للحاسوب وتعيد كائنًا يحتوي على الخصائصComputerName
وStatus
.
Get-ConnectionStatus
تمرر بعد ذلك كل كائن إلى cmdletForEach-Object
، الذي يعيد سلسلة واحدة ملونة باللون السماوي مع حالة قابلة للقراءة للإنسان.
ربط الأنابيب عن طريق اسم الخاصية
حتى الآن، تم تكوين cmdlet Get-ConnectionStatus
لقبول إدخال الأنبوب بالقيمة (ValueFromPipeline
) عن طريق قبول مصفوفة من السلاسل مثل '127.0.0.1', '192.168.1.100'
. هل ستعمل هذه الوظيفة كما هو متوقع إذا كان الإدخال مأخوذًا من ملف CSV بدلاً من ملف نصي لعناوين IP؟
ربما لديك ملف CSV يبدو كما هو موضح أدناه في C:\Test\pc-list.csv.
يرجى ملاحظة أن حقل
ComputerName
في ملف CSV هو نفس اسمComputerName
فيGet-ConnnectionStatus
ComputerName
parameter.
إذا كنت تحاول استيراد الملف CSV وتمريره عبر الأنبوب إلى Get-ConnectionStatus
، ستعيد الوظيفة نتيجة غير متوقعة في عمود ComputerName
.
هل يمكنك تخمين ما الذي حدث خطأ؟ بعد كل شيء، اسم المعلمة متطابق، لذلك لماذا لم تربط أنبوبة PowerShell الإخراج الذي أرجعته Import-CSV
بالمعلمة ComputerName
في Get-ConnectionStatus
؟ لأنك بحاجة إلى سمة المعلمة ValueFromPipelineByPropertyName
.
في الوقت الحالي، لدى معلمة ComputerName
في الوظيفة تعريف معلمة يبدو على النحو التالي [Parameter(ValueFromPipeline)]
. لذلك، يجب عليك إضافة ValueFromPipelineByPropertyName
لتعيين معلمة ComputerName
لدعم الإدخال بالاسم، كما هو موضح أدناه.
بمجرد أن يكون لديك دعم أنبوبة بواسطة الاسم، تخبر PowerShell بالبدء في النظر إلى أسماء خصائص الكائن ونوع الكائن. بمجرد أن تقوم بهذا التغيير، يجب أن ترى الإخراج المتوقع بعد ذلك.
ملخص
في هذا البرنامج التعليمي، تعلمت كيفية عمل أنبوبة PowerShell، وكيفية ربط المعلمات، وحتى كيفية إنشاء وظيفة خاصة بك تدعم أنبوبة PowerShell.
على الرغم من أن الوظائف ستعمل بدون الأنبوبة، إلا أنها لن تقوم بـ “تيار” الكائنات من أمر إلى آخر وتبسيط الكود.
هل يمكنك التفكير في وظيفة قمت بكتابتها، أو ربما على وشك كتابتها، التي يمكن أن تستفيد من جعلها جاهزة للأنبوبة؟