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
如果可能,我需要将所有内容保存在一个脚本中。
答案 0 :(得分:2)
注意:Start-Process
的参与使解决方案显着复杂化 - 见下文。我从PowerShell直接调用了 f powershell
,你可以安全地传递一个脚本块,如下所示:
powershell (Get-Command Check-PC).ScriptBlock # !! Does NOT work with Start-Process
带有辅助自删除临时文件的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
实例将无法看到您当前会话的定义(除非它们已在您的个人资料中定义),因此您必须通过功能的主体到它(要执行的源代码)。
(Get-Command -Type Function Check-PC).Definition
将您的函数定义的 body 作为字符串返回。
字符串需要转义,但是要传递给新的Powershell进程未修改。
除非它们被表示为"
或三倍(\"
),否则会剥离字符串中嵌入的"""
个实例。
在这种情况下,需要\"
而不是通常的`"
来转义双引号,因为PowerShell在将命令传递给\"
可执行文件时需要powershell.exe
。)
同样,如果函数体内的字符串作为整体或双引号字符串以({1}}的非空运行结束,那么\
将被解释为 escape 字符,因此\
必须加倍。谢谢,PetSerAl。
绕过这些引用(转义)令人头疼的最强大的方法是将Base64编码的字符串与\
参数结合使用:
-EncodedCommand
从[Convert]::ToBase64String()
数组创建Base64编码的字符串。
[byte[]]
转换(内部UTF-16 -
" [Text.Encoding]::Unicode.GetBytes()
")字符串到Unicode
数组。
如果您想要传递完整功能,那么可以通过名称调用以传递参数 < / strong>,需要做更多的工作。
[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")))
解决方案,使用基于正则表达式的源代码转义传递:PetSerAl建议使用正则表达式执行转义的以下替代方法。 解决方案更简洁,但有些令人费解:
Start-Process
Start-Process powershell -args '-noprofile', '-noexit', '-Command', `
('"' +
((Get-Command -Type Function Check-PC).Definition -replace '"|\\(?=\\*("|$))', '\$&') +
'"')
匹配每个"|\\(?=\\*("|$))
个实例和每个非"
个字符的运行。 - 逐个字符 - 直接在\
字符之前。或者字符串的最后一部分。
"
来逃避单个文字\\
。\
是一个积极的前瞻断言,仅当(?=\\*("|$))
后跟\
或字符串末尾("
)时才匹配$
中间的其他\
个实例(\\*
)。请注意,由于断言不会对匹配产生影响,因此\
字符(如果存在多个字符)仍然是逐个匹配的。 \$&
将每个匹配的字符替换为\
后跟字符本身($&
) - 请参阅我的this answer以了解您可以使用的结构-replace
表达式的替换字符串。
需要将结果包含在"..."
('"' + ... + '"'
)中以防止空格正常化;没有它,任何超过一个空格char的运行。和/或tab char。将被标准化为单个空格,因为整个字符串不会被识别为单个参数。
powershell
,PowerShell通常会自动将字符串括在"..."
幕后,因为它对于在调用外部实用程序(本机命令行应用程序)时包含空格的参数执行此操作,这是powershell.exe
的原因 - 与Start-Process
cmdlet <不同/ em>的