gpt4 book ai didi

powershell - 在新窗口中运行PowerShell自定义函数

转载 作者:行者123 更新时间:2023-12-03 00:46:11 25 4
gpt4 key购买 nike

Function Check-PC
{
$PC = Read-Host "PC Name"
If($PC -eq "exit"){EXIT}
Else{
Write-Host "Pinging $PC to confirm status..."
PING -n 1 $PC
}

这是我已编写到PowerShell脚本中的函数的摘要。我希望该功能在PowerShell的新实例中运行,而不是在主窗口中运行。

是否可以在单独的PowerShell过程中运行此程序而无需将其编写为单独的脚本并调用该脚本?像这样:
$x= Start-Process powershell | Check-PC

如果可能,我需要将所有内容保存在一个脚本中。

最佳答案

注意:Start-Process的参与使解决方案非常复杂-请参见下文。如果从PowerShell直接调用powershell,则可以安全地传递脚本块,如下所示:

powershell ${function:Check-PC}  # !! Does NOT work with Start-Process
${function:Check-PC}variable namespace notation的一个实例:它以脚本块的形式返回函数的主体( [scriptblock]实例);它与 Get-Content Function:Check-PC更加简洁,快捷。

如果需要将(仅限位置的)参数传递给脚本块,则必须附加 -Args,后跟参数作为数组( , -separated)。

带有辅助自删除临时文件的 Start-Process解决方案:

有关相关问题,请参见 this answer的下半部分。

带有 Start-Process和Base64编码的 -EncodedCommand解决方案:
Start-Process powershell -args '-noprofile', '-noexit', '-EncodedCommand', `
([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes(
(Get-Command -Type Function Check-PC).Definition)))

新的 powershell实例将看不到当前 session 的定义(除非在配置文件中定义了它们),因此 必须将函数体传递给它(要执行的源代码)。

(Get-Command -Type Function Check-PC).Definition 以字符串形式返回函数定义的主体。

但是,该字符串需要转义,以便未经修改地传递到新的Powershell进程。
除非嵌入在字符串中的 "实例被表示为 \"或三元组( """),否则它们将被剥离。
(在这种情况下,需要 \"而不是通常的 `"来转义双引号,因为在将命令传递给 \"可执行文件时,PowerShell期望 powershell.exe。)

类似地,如果整个字符串或函数主体中带双引号的字符串以 \结尾(非空运行),则该 \将被解释为转义字符,因此 \必须加倍。谢谢, PetSerAl

绕过这些引号(转义)麻烦的最可靠方法是结合使用Baset编码的字符串和-EncodedCommand参数:
  • [Convert]::ToBase64String()[byte[]]数组创建Base64编码的字符串。
  • [Text.Encoding]::Unicode.GetBytes()转换(内部UTF-16-
    Unicode”)字符串转换为[byte[]]数组。


  • 如果要传递完整功能,则可以按名称调用它以传递参数,需要做更多的工作。
    # Simply wrapping the body in `function <name> { ... }` is enough.
    $func = (Get-Command -Type Function Check-PC)
    $wholeFuncDef = 'Function ' + $func.Name + " {`n" + $func.Definition + "`n}"

    Start-Process powershell -args '-noprofile', '-noexit', '-EncodedCommand', `
    ([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes("$wholeFuncDef; Check-PC")))

    带有基于正则表达式的转义的 Start-Process解决方案,以传递源代码:

    PetSerAl建议使用以下替代方法,该方法使用正则表达式执行转义。
    解决方案更加简洁,但有些弯腰:
    Start-Process powershell -args '-noprofile', '-noexit', '-Command', `
    ('"' +
    ((Get-Command -Type Function Check-PC).Definition -replace '"|\\(?=\\*("|$))', '\$&') +
    '"')
  • "|\\(?=\\*("|$))与每个"实例以及\字符的每个非空运行匹配。 -一个字符一个字符-直接在"字符之前。或字符串的末尾。

    在正则表达式的上下文中需要
  • \\,以转义单个文字\
  • (?=\\*("|$))是一个肯定的前瞻性断言,仅当直接在其后跟随\或字符串的结尾(")或在两者之间的其他$实例(\)时,才匹配\\*。请注意,由于断言对匹配没有帮助,因此\字符(如果有多个)仍然一一匹配。
  • \$&将每个匹配的字符替换为\,然后替换为字符本身($&)-有关可在-replace表达式的替换字符串中使用的结构,请参阅我的this answer
  • 需要将结果包含在"..."('"' + ... + '"')中,以防止空格标准化;没有它,任何运行都会超过一个空格字符。和/或制表符。将被归一化为单个空格,因为整个字符串不会被识别为单个参数。
  • 请注意,如果您要直接调用powershell,PowerShell通常会自动在幕后将字符串包含在"..."中,因为调用外部实用程序(本机命令行应用程序)时,包含空格的参数会这样做。 powershell.exe是-与Start-Process cmdlet不同。
  • PetSerAl指出,自动双引号机制并不是那么简单(字符串的特定内容与是否应用自动双引号有关),并且特定行为在v5中有所更改,然后再次更改(略)在v6中。
  • 关于powershell - 在新窗口中运行PowerShell自定义函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44981177/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com