הצינורות של PowerShell הן אחת מתכונות החשובות (והשימושיות) ביותר של קלף הפקודות של PowerShell ושפת התסריטים שלו. ברגע שתבינו את היסודות של איך זה עובד ומה הוא מסוגל לעשות, תוכלו להשתמש בכוחו בפונקציות שלכם. במדריך הזה, אתם הולכים לעשות בדיוק זאת!
הצינור של PowerShell מאפשר לכם לשרשר יחד פקודות כדי לבנות 'צינור' אחד שמפשט קוד, מאפשר עיבוד מקבילי ועוד. אם אתם מוכנים ללמוד על הצינור ולבנות פונקציות משלכם כדי להשתמש בצינור, בואו נתחיל!
דרישות מוקדמות
הפוסט הזה יהיה מדריך ויכלול הדגמות מעשיות. אם ברצונכם לעקוב, יהיה עליכם להשתמש ב- PowerShell v3+. במדריך זה נעשה שימוש ב- Windows PowerShell v5.1.
הבנת הצינור ב- PowerShell
רוב פקודות ה- PowerShell מקבלות קלט דרך פרמטר. הפקודה מקבלת אובייקט מסוים כקלט ועושה משהו עם זה בפנים. לאחר מכן, היא מחזירה אובייקט אחרי פלט אופציונלי.
פקודות בצינור פועלות כמו רצים אנושיים במכירת השתייה. כל רץ במרוץ, למעט הראשון והאחרון, מקבל את המקל (אובייקטים) מהקודם ומעביר אותו לבא.
לדוגמה, ל-Stop-Service
cmdlet יש פרמטר בשם InputObject
. פרמטר זה מאפשר לך להעביר סוג מסוים של אובייקט אל Stop-Service
המייצג את השירות של Windows שתרצה לעצור.
כדי להשתמש בפרמטר InputObject
, ניתן לאחזר את אובייקט השירות באמצעות Get-Service
ולאחר מכן להעביר את האובייקט לפרמטר InputObject
כפי שמוצג למטה. שיטה זו לספק קלט ל-Stop-Service
cmdlet דרך הפרמטר InputObject
עובדת מצוין ומבצעת את המשימה.
שיטה זו להעברת קלט לפקודת Stop-Service
דורשת שני שלבים נפרדים. PowerShell חייב להפעיל Get-Service
תחילה, לשמור את הפלט במשתנה ואז להעביר את הערך הזה ל-Stop-Service
דרך הפרמטר InputObject
.
כעת, נצמצם את קטע הקוד לעיל עם קטע הקוד למטה, המבצע את אותה הדבר. זה קל יותר משום שאין צורך ליצור משתנה $services
או אפילו להשתמש בפרמטר InputObject
בכלל. במקום זאת, PowerShell "יודע" שתכוונת להשתמש בפרמטר InputObject
. הוא עושה זאת דרך מושג שנקרא קישור פרמטרים.
עכשיו, חיברת פקודות ביחד עם האופרטור |
. יצרת צינור.
אך, אין צורך להשתמש רק בשתי פקודות כדי ליצור צינור; ניתן לרצוף כמה שתרצה (אם הפרמטרים של הפקודות תומכים בזה). לדוגמה, קטע הקוד למטה:
- עובר על כל האובייקטים שהפקודה
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
המוכנה לקבל קלט מצינור בפרמטרByPropertyName
. כאשר אתה מעביר אובייקט עם מאפיין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: הוספת בלוק עיבוד
כאשר ברצונך ש־PowerShell יעבוד עם כל האובייקטים שנשלחים מהצינור, עליך להוסיף בלוק Process
. בלוק זה אומר ל־PowerShell ל־עבד כל אובייקט הנשלח מהצינור.
בלעדיו של בלוק
Process
, PowerShell יעבד רק את האובייקט הראשון הנשלח מהצינור. בלוקProcess
אומר ל־PowerShell להמשיך לעבד אובייקטים.
הוסף בלוק Process
כמצויין מטה על ידי לאחוז את כל הפונקציונליות של הפונקציה.
תמיד שלח את הפלט מבתוך הבלוק
Process
. שליחת הפלט מבתוך הבלוקProcess
"משדרת" את האובייקטים לפייפליין ומאפשרת לפקודות אחרות לקבל את האובייקטים האלה מהפייפליין.
מעבר אובייקטים לפייפליין של PowerShell
פעם שיש לך בלוק Process
מוגדר בפונקציה למעלה, כעת אתה יכול לקרוא לפונקציה ולהעביר ערכים לפרמטר ComputerName
באמצעות הפייפליין כפי שמוצג למטה.
בנקודה זו, תוכל לנצל את הכוח האמיתי של הפייפליין ולהתחיל לכלול פקודות נוספות במערכת. לדוגמה, אולי יש לך קובץ טקסט, C:\Test\computers.txt, עם שורה של כתובות IP מופרדות באמצעות שורה חדשה כמו שמוצג למטה.
אז תוכל להשתמש בפקודת ה- Get-Content
כדי לקרוא כל אחת מאותן כתובות IP בקובץ הטקסט ולהעביר אותן ישירות לפונקציית Get-ConnectionStatus
.
לקחת את ההגדרה הזו צעד אחד קדימה, תוכל לשלוף את האובייקטים ש- Get-ConnectionStatus
מחזירה ישירות לפקודת ה- ForEach-Object
.
הקוד הבא:
- קורא את כל שמות המחשבים בקובץ הטקסט ומעביר אותם לפונקציית
Get-ConnectionStatus
. Get-ConnectionStatus
מעבדת כל שם מחשב ומחזירה אובייקט עם התכונותComputerName
ו-Status
.Get-ConnectionStatus
מעבירה לאחר מכן כל אובייקט לפקודתForEach-Object
, שמחזירה מחרוזת יחידה בצבע כחול עם סטטוס שקריא לאדם.
אם קליטת הצינור לא הופעלה על הפרמטר
ComputerName
או אםGet-ConnectionStatus
לא החזירה אובייקט בתוך בלוק ה-Process
, PowerShell לא היה מחזיר שום סטטוס למסוף עד שכל האובייקטים (כתובות IP) יועברו.
קשירת צינור על פי שם המאפיין
עד כה, פקודת Get-ConnectionStatus
מוגדרת לקבל קלט צינור לפי הערך (ValueFromPipeline
) על ידי קבלת מערך של מחרוזות כמו '127.0.0.1', '192.168.1.100'
. האם פונקציה זו תעבוד גם עם קלט שיקבל מקובץ CSV בניגוד לקובץ טקסט של כתובות IP?
אולי יש לך קובץ CSV שנראה כמו מטה ב- C:\Test\pc-list.csv.
שים לב ששדה
ComputerName
בקובץ ה-CSV הוא אותו שם כמו הפרמטרComputerName
שלGet-ConnnectionStatus
.
אם תנסה לייבא את ה-CSV ולהעביר אותו דרך הצינור ל-Get-ConnectionStatus
, הפונקציה תחזיר תוצאה בלתי צפויה בעמודה ComputerName
.
האם תצליח לנחש מה השתבש? לאחר הכל, שם הפרמטר תואם, אז למה לא קישרה צינורות הפוורשל של PowerShell את הפלט שהחזיר Import-CSV
לפרמטר ה-ComputerName
ב־Get-ConnectionStatus
? מכיוון שאתה צריך את המאפיין הפרמטר ValueFromPipelineByPropertyName
.
כרגע, לפרמטר ה-ComputerName
של הפונקציה יש הגדרת פרמטר הנראית כמו [Parameter(ValueFromPipeline)]
. לכן, עליך להוסיף ValueFromPipelineByPropertyName
כדי להגדיר את פרמטר ה־ComputerName
כך שיתמוך בקלט לפי שם המאפיין, כפי שמוצג למטה.
כאשר יש לך תמיכה בצינורות לפי שם המאפיין, אתה אומר לפוורשל של PowerShell להתחיל לחפש בשמות המאפיינים של האובייקט וסוג האובייקט. לאחר שעשית את השינוי הזה, אתה אמור לראות את הפלט המצופה.
סיכום
במדריך זה, למדת כיצד עובד צינור הפוורשל של PowerShell, כיצד הוא מקשר פרמטרים, ואפילו כיצד ליצור פונקציה משלך שתתמוך בצינור הפוורשל של PowerShell.
אף על פי שפונקציות תעבוד בלי הצינור, הן לא יעבירו "שזרימה" של אובייקטים מפקודה אחת לאחרת ויפשיטו קוד.
האם יש לך פונקציה שכתבת, או אולי מתכוון לכתוב, שיכולה להרוויח מהפכה להיות מוכנה לצינור?