התחלת תהליך בפוורשל: הפעלת תהליכים אינטואיטיבית

על מנת להבין למה Start-Process וכל הפקודות הללו מוגבלות, עליך להבין תחילה איך קובץ EXE טיפיקלי פועל. כאשר קובץ EXE נפתח, הוא מבצע את הפעולה שנוצבע לו; הוא יכול לשלוח פינג (ping), להתחיל מתקין תוכנה (setup), לחפש רשומת DNS (nslookup), וכו'. לכן, עבור חלק זה ועבור פקודות כמו Start-Process, הפעולה יעילה. זה פשוט. ההגבלה מתגלה כאשר ה-EXE מחזיר פלט.

אנו יכולים להתחיל תהליך ב-PowerShell בכמה דרכים שונות. יש לנו את ה-Start-Process של PowerShell ואת ה-Invoke-Expression, נוכל לקרוא לקובץ הנוצר ישירות או להשתמש ב-ampersand (&) כדי להפעיל ביטויים. הדרך הנפוצה ביותר היא להשתמש ב-Start-Process משום שזו כנראה הדרך הבלתי מסובכת ביותר. PowerShell נודעת בגישה אינטואיטיבית לשמות פקודות, ו-Start-Process היא בחירה מצוינת. אך, הפקודה הזו מוגבלת.

זרמים

קובץ EXE, כמו קבצי יישומים אחרים לא נגבלים לחלונות, יש לו מושג של זרמים סטנדרטיים. זרמים סטנדרטיים הם אופן בו קבצים ניתןים להחזיר פלט. יש שלושה סוגים של זרמים; stdin, stdout ו-stderr. Stdin הוא הזרם שניתן להעביר אל הקובץ הניתן להפעיל, עליו לא נתעקש כאן. Stdout הוא הזרם שהקובץ הניתן להפעיל משתמש בו כדי לשלוח פלט רגיל לא שגוי.

במונחים של PowerShell, חשב על stdout כמה ש-Write-Output מחזיר. כאשר קורה שגיאה (תלוי בכך האם מפתח התוכנית כתב את זה נכון), התוכנית צריכה להחזיר פלט דרך stderr. זהו זרם שמיועד להחזיר מידע על שגיאות.

זרמים אלו מאפשרים למשתמשים של קבצי הביצוע להבחין בין הפלט הרגיל ובין שגיאה. זרמים היו קיימים זמן רב ולכן Windows ו-PowerShell מכירים אותם ומשתמשים בהם מאז.

קודי יציאה

קוד יציאה, קוד החזרה או קוד תוצאה הוא עוד מושג עתיק שקבצי הביצוע עוקבים אחריו. קוד יציאה הוא מספר שלם שמאפשר לקובץ הביצוע להודיע על מצבו למשתמש כאשר הוא יוצא.

קיימים כמה קודי יציאה סטנדרטיים שצריך לעקוב אחריהם, למשל אם קוד היציאה הוא 0, הכל בסדר, קוד היציאה 3010 אומר שיש צורך באיתחול וכו'. PowerShell יכול לכוד את קוד יציאה זה בכמה דרכים שונות כמו שימוש במשתנה האוטומטי $LastExitCode. קודי היציאה הם דרך נוספת שבה הקובץ הביצוע מתקשר למשתמש.

לכידת זרמים וקודי יציאה

עכשיו שהבנת איך אנו עובדים נשתמש בדוגמה. כדי לשמור על זה פשוט, אשתמש ב־ping.exe. תחילה, אשתמש בפקודה ping לכתובת google.com שתחזיר תוצאה מוצלחת. אנחנו לא משתמשים כאן בתהליך התחלת PowerShell.

PS C:\> ping google.com
Pinging google.com [2607:f8b0:4004:80b::200e] with 32 bytes of data:

Reply from 2607:f8b0:4004:80b::200e: time=61ms
Reply from 2607:f8b0:4004:80b::200e: time=65ms
Reply from 2607:f8b0:4004:80b::200e: time=80ms
Reply from 2607:f8b0:4004:80b::200e: time=78ms

Ping statistics for 2607:f8b0:4004:80b::200e:

Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 61ms, Maximum = 80ms, Average = 71ms

PS> $LastExitCode
0
PS> $?
True

I’ll now purposefully ping a host that doesn’t resolve a DNS name and will fail. Notice the value of $LastExitCode.

PS> ping googlllll.com

Ping request could not find host googlllll.com. Please check the name and try again.
PS> $LASTEXITCODE
1

ראית שקוד היציאה שונה מכיוון שתוצאת הפינג הייתה שונה אבל לא ראית נתונים כי פוורשל לא מבין את ההבדל כשמדובר בקבצי ניתוב תכנותיים. הטקסט שאתה רואה במסוף הוא לבן; לא הטקסט השגיאה האדום שאתה מכיר ואוהב.

נוכל לתפוס את הנתונים ולהפנות אותם לקבצים בכמה דרכים שונות כמו שימוש ב־> ו־2> כמו שמוצג למטה. זהו הדרך הישנה.

PS> ping googllll.com > output.msg 2> output.err
PS> Get-Content .\output.err
PS> Get-Content .\output.msg

Ping request could not find host googllll.com. Please check the name and try again.

שים לב עם זאת, במקרה זה, אף על פי ש־ping.exe מחזיר קוד יציאה של 1 (כפי שמוצג לעיל), הפלט עדיין הולך ל־stdout. זה די נפוץ. איזה נתון וקוד יציאה שמוחזרים זה נעצר על ידי המפתח ומגיעים בסגנונות רבים שונים, למרבה המצטער.

אם תרצה ללכת לדרך "החדשה" תוכל להשתמש ב־Start-Process ולהשתמש בפרמטרים -RedirectStandardError ו־-RedirectStandardOutput, אך הם עדיין יישלחו רק לקבצים.

מגבלות של Start-Process

תראה שהתחלת תהליך והחזרת פלט מקובץ לא נפוץ במיוחד. בנוסף, פוורשל לא מטפל בנתונים ובקודי יציאה בצורה טובה מדי. אם הייתי רוצה להשתמש ב־Start-process כדי להריץ ping.exe ולרצות לעקוב מה קרה בתוצאה, יהיה עליי לעשות משהו כמו זה כל פעם שארצה להריץ קובץ ניתוב.

PS> Start-Process -FilePath -NoNewWindow ping -ArgumentList 'google.com' -RedirectStandardOutput output.txt -RedirectStandardError err.txt
PS> $LastExitCode
PS> Get-Content -Path output.txt
PS> Get-Content -Path err.txt

I still wouldn’t get my error text either!

בוא נתקן את כל זה. הורד פונקציה קטנה שיצרתי בשם Invoke-Process מגלריית PowerShell.

PS> Install-Script 'Invoke-Process'
PS> . Invoke-Process.ps1

עכשיו הרץ את הפינג באמצעות מארח תקין וצפה מה יקרה.

Invoke-Process -FilePath ping -ArgumentList ‘google.com’

השם לִכְתוֹבֶת הַאֲיַפָּיָים אוֹ השם הַנוֹתֵן מִדַּעַת פֵּלָא, אֲם אֵינְךָ בָּטוֹחַ בְּהִיעָרוֹת, אֶל תְּבַצֵּעַ פְּעוּלָה זוֹ.

עַכְשָׁיו הַרְץ פִּינְג בְּאַמְצָעוּיוֹת שֶׁלֹּא חוּקִית.

Invoke-Process -FilePath ping -ArgumentList ‘googlddde.com’

עַכְשָׁו תַּפְסִיק שְׁנֵהֶגֶיה לָאָדוֹם הַטִקסט שֶׁגַּם זֶה נָכוֹן לְצַפוֹת בּוֹ כְּאָמוּר.Invoke-Process מַשְׁתִּמֵשׁ Start-Process תַּחְתִּיו לְתָפוּס stdout, stderr, וְקוֹד יְצִיאָה וְאָז שׁוֹלֵחַ אֶת הַפַּלט לַזְרוֹם שֶׁהוּא צָרִיך לָלֶכֶת אֵלָיו. זֶה כְּךָ הוּא!

חָבְל שֶׁפֹּוֵורְשֶׁלַפֵוֶר לֹא עָשָׂה זֶה קָל יוֹתֵר לַעֲבוֹד עִם זַרְמִים וּקוֹדֵי יְצִיאָה מִקוֹבְצִים בִּיצוּר, אֲבָל אֲנִי מְנַחֵשׁ שֶׁיֵּשׁ לְהוֹסִיף אֶת זֶה שָׁם עַכְשָׁו שֶׁזֶה פָּתוּחַ!

Source:
https://adamtheautomator.com/start-process/