【问题标题】:PowerShell Invoke-Command with FilePath on local computer - vague parameters error?PowerShell Invoke-Command 与本地计算机上的 FilePath - 模糊参数错误?
【发布时间】:2020-07-13 17:34:44
【问题描述】:

我想使用 Invoke-Command 在本地机器上的文件中运行脚本,这样我就可以使用 -ArgumentList 传入参数。我遇到了一个我不明白的错误,所以我简化了我的命令。当我这样做时:

Invoke-Command -FilePath 'getprocess.ps1'

getprocess.ps1的内容是:

Get-Process

我得到的错误信息是:

Invoke-Command:无法使用指定的命名参数解析参数集。

在 line:1 char:1

+ Invoke-Command -FilePath 'getprocess.ps1'

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~

+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException

+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeCommandCommand

我对这个错误消息感到困惑。这是什么意思?我该如何让它发挥作用?

【问题讨论】:

    标签: powershell invoke-command


    【解决方案1】:

    tl;dr

    • 一般情况下,不要将Invoke-Command 用于本地 调用 - 虽然技术上可行,但只有一个特定用例需要这样做(见下文)。

    • 相反,直接调用脚本

    .\getprocess.ps1
    

    注意:与cmd.exe 不同,PowerShell 在设计上需要.\ 才能执行位于当前目录 中的可执行文件。也就是说,为了避免意外执行当前目录而不是$env:Path 中列出的目录中的可执行文件,PowerShell 作为一项安全功能,要求您明确表示要在当前目录(.)中执行某些内容的意图.

    对于script blocks ({ ... }),使用&call operator(例如& { Get-Date })。

    仅出于句法原因,您在情境上还需要&作为脚本文件路径,如果它们被指定为引用路径(例如,& '.\getprocess.ps1')和/或如果路径涉及变量引用(例如,
    & $HOME\getprocess.ps1)。

    (另外,. dot-sourcing operator两种 情况下都需要,以便在调用者的范围内直接执行脚本 [block] 而不是在子范围)。


    请注意,您可以在技术上结合将脚本块传递给Invoke-Command(参数-ScriptBlock)与调用本地脚本

    # The script block positionally binds to the -ScriptBlock parameter.
    # This is essentially the more expensive equivalent of:
    #     & .\getprocess.ps1
    Invoke-Command { .\getprocess.ps1 }
    

    速度较慢,并且与直接调用相比没有任何优势。 但是,有一个可以想象的用例

    如果脚本不是 advanced script 并且您想利用 Invoke-Command 的流输出收集 common parameters, such as -ErrorVariable(如果被调用的脚本或函数高级的,它支持这些常用参数本身)。

    # Invoke locally and collect errors in $errs
    Invoke-Command { .\getprocess.ps1 } -ErrorVariable errs
    

    警告:至少从 PowerShell 7.2 开始,Invoke-Command 不会common -ErrorAction parameter 应用于脚本块中发生的错误 >,所以不能用来控制错误处理;例如,-ErrorAction Stop 对脚本块中的命令没有影响。


    至于你尝试了什么

    确实,正如您指出的in your own answer-FilePath 必须
    -ComputerName 参数
    结合使用(错误消息是如此通用很不幸)。

    参数-FilePath目的是将本地脚本(*.ps1文件)的内容复制到远程 em> 执行计算机那里。也就是说,它是一种执行脚本代码的便捷机制,该脚本(仅)在远程机器上本地可用。

    虽然您可以通过-ComputerName localhost(或者,更简洁地,通过-ComputerName ./-cn .)在技术上定位本地计算机,但这确实 相当于本地通话

    无论何时指定 -ComputerName - 即使是 -ComputerName localhost - PowerShell 的远程基础架构 都会被使用,它具有主要影响

    • 目标计算机 - 即使它是本地计算机 - 也必须设置为 PowerShell 远程处理 - 请参阅 about_Remote_Requirements

    • 如果您专门针对本地计算机,您必须在提升会话中运行(以管理员身份运行)。

    • 执行将比直接(本地)调用慢得多。

    • 考虑到通过 PowerShell 的基于 XML 的序列化基础设施进行跨进程封送处理,输入和输出数据都可能丢失类型保真度 - 请参阅 this answer


    也就是说,如果意图是在本地测试远程执行您的脚本,并且您的本地机器被设置为远程目标,那么使用@987654362 @ (-ComputerName . / -cn .) 非常有意义,因为 PowerShell 的远程处理基础架构随后以与真正远程调用相同的方式参与。

    但请注意,此类“环回远程处理”调用需要 elevation(以管理员身份运行)。

    【讨论】:

    • 对于更一般的“当脚本位于本地计算机上的文件中时,在本地计算机上调用脚本的推荐方法是什么?”这将是一个很好的答案?但我的问题是关于使用 Invoke-Command,这是我在特定情况下需要的。我不想用一段励志背景信息来夸大我的问题,以免谈话变成关于我的动机而不是我的问题。看起来还是有的。
    • @BigScary, Invoke-Command 通常是错误的工具,用于调用本地脚本文件。我的回答集中在这一点上,因为这是对未来读者最重要的信息。但是,我在答案中添加了一个用例,其中本地使用 Invoke-Command 可能有意义,但它需要使用不同的参数,即 -ScriptBlock 和一个脚本块,从中调用脚本文件。跨度>
    【解决方案2】:

    虽然错误消息没有说明清楚,但 -FilePath 参数使 -ComputerName 参数成为必需参数。要明确定位本地计算机,请使用 -ComputerName localhost

    Invoke-Command -FilePath 'getprocess.ps1' -ComputerName localhost
    

    【讨论】:

    • 您的回答在技术上是正确的(这就是我投票赞成它的原因),但是将 -ComputerName localhost 呈现为 local 调用会产生误导,原因详见我的答案。简而言之,没有充分的理由使用Invoke-Command 进行本地调用。 (如果是你否决了我的答案,我邀请你对其具体观点提出异议。)
    • 再想一想,我认为造成-ComputerName localhost适合本地调用脚本的误导性印象胜过有关所需参数组合的信息的技术正确性。
    【解决方案3】:

    您可以像这样在本地运行它,但您必须在管理员(提升的)提示符下运行。能够作为测试运行它真是太好了。

    invoke-command localhost getprocess.ps1
    

    实际上你也可以做一种奇怪的并行:

    invoke-command localhost,localhost,localhost getprocess.ps1
    

    【讨论】:

      【解决方案4】:

      您必须有一个计算机名。

      $parameters = @{
          ComputerName = '255.255.255.255'
          FilePath = 'getprocess.ps1'
          Credential = 'Domain01\User01'
      }
      
      invoke-command @parameters
      

      使用您的 IP :) 要允许您还必须包含 -credential

      如果这样不行...invoke-expression 可能是测试的半合适替代品,直到您准备好在远程机器上调用命令。

      【讨论】:

      • 听起来 OP 的意图是调用 locally,在这种情况下,Invoke-Command 完全是错误的工具。建议使用Invoke-Expression 是有问题的,不仅因为在这种情况下没有必要,还因为it should generally be avoided。也就是说,即使在极少数情况下,它的使用是合理和必要的,建议一般不要使用它。
      • 我同意生产脚本的这一点,但使用受信任的来源进行测试很好。
      【解决方案5】:

      我真的不能在本地使用invoke-command。当您尝试在远程 PC 上运行命令时使用它。

      例如,你会想要运行类似的东西:

      invoke-Command -ComputerName REMOTE-PC -Credentials $credential -Scriptblock {Get-Process}
      

      该错误基本上是在告诉您需要填写更多与该命令相关的参数。

      尝试运行Get-Help Invoke-Command 以查看有关该命令的一些信息以及如何运行它。

      【讨论】:

      • 明确一点:投反对票的不是我(相反)。你说得对,Invoke-Command 主要用于 远程 调用,但你可以使用它在本地调用命令,即如果 脚本块 i> 被传递给-ScriptBlock,而-FilePath 确实需要使用-ComputerName。也就是说,没有充分的理由在本地使用 Invoke-Command
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-29
      相关资源
      最近更新 更多