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
}
Run Code Online (Sandbox Code Playgroud)
这是我写到 PowerShell 脚本中的一个函数片段。我希望该函数在 PowerShell 的新实例中运行,而不是在主窗口中运行。
是否可以在 PowerShell 的单独进程中运行它而不将其编写为单独的脚本并调用脚本?像这样的东西:
$x= Start-Process powershell | Check-PC
Run Code Online (Sandbox Code Playgroud)
如果可能,我需要将所有内容都保存在一个脚本中。
注意:正是参与Start-Process使解决方案显着复杂化 - 见下文。我˚Fpowershell被调用直接从PowerShell中,你可以放心地通过一个脚本块,如下所示:
powershell ${function:Check-PC} # !! Does NOT work with Start-Process
Run Code Online (Sandbox Code Playgroud)
${function:Check-PC}是变量命名空间符号的实例:它以脚本块(实例)的形式返回函数体;它是更简洁、更快速的.[scriptblock]Get-Content Function:Check-PC
如果您需要将(仅位置)参数传递给脚本块,则必须附加-Args,然后将参数作为数组(,-separated )。
Start-Process 带有辅助自删除临时文件的解决方案:Start-Process使用-EncodedCommandBase64 编码的解决方案:Start-Process powershell -args '-noprofile', '-noexit', '-EncodedCommand', `
([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes(
(Get-Command -Type Function Check-PC).Definition)))
Run Code Online (Sandbox Code Playgroud)
新powershell实例不会看到您当前会话的定义(除非它们在您的配置文件中定义),因此您必须将函数体传递给它(要执行的源代码)。
(Get-Command -Type Function Check-PC).Definition将函数定义的主体作为string 返回。
但是,该字符串需要转义,以便在未修改的情况下传递给新的 Powershell 进程。
"嵌入在字符串中的实例将被剥离,除非它们被表示为\"或三倍 ( """)。
(在这种情况下,\"通常`"需要转义双引号,因为 PowerShell\"在将命令传递给powershell.exe可执行文件时需要。)
类似地,如果整个字符串或函数体内的双引号字符串以 (a non-empty run of) 结尾\,\则将被解释为转义字符,因此\必须加倍。谢谢,PetSerAl。
绕过这些引用(转义)问题-EncodedCommand的最可靠方法是将 Base64 编码的字符串与参数结合使用:
[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")))
Run Code Online (Sandbox Code Playgroud)
Start-Process 使用基于正则表达式的源代码转义的解决方案:PetSerAl建议使用以下替代方案,它使用正则表达式来执行转义。解决方案更简洁,但有点令人费解:
Start-Process powershell -args '-noprofile', '-noexit', '-Command', `
('"' +
((Get-Command -Type Function Check-PC).Definition -replace '"|\\(?=\\*("|$))', '\$&') +
'"')
Run Code Online (Sandbox Code Playgroud)
"|\\(?=\\*("|$))匹配每个"实例和每个非空\字符运行。- 逐个字符 - 直接在"字符之前。或字符串的最末端。
\\需要在正则表达式的上下文中转义单个文字\.(?=\\*("|$))是一个肯定的前瞻断言,它\仅在后跟"字符串 ( $)或结尾时匹配,或者直接匹配,或者\在 ( \\*)之间有更多实例。请注意,由于断言对匹配没有贡献\,因此如果有多个字符,仍然会一一匹配。\$&用 a\后跟字符本身 ( $&)替换每个匹配的字符- 请参阅此答案以了解您可以在-replace表达式的替换字符串中使用的构造。
需要将结果括在"..."( '"' + ... + '"') 中以防止空格规范化;没有它,任何超过一个空格字符的运行。和/或制表符。将被规范化为单个空格,因为整个字符串不会被识别为单个参数。
powershell 直接调用,PowerShell 通常会在幕后自动将字符串括起来"...",因为它会在调用外部实用程序(本机命令行应用程序)时对包含空格的参数这样做,这powershell.exe与 - 不同该Start-Process cmdlet的。| 归档时间: |
|
| 查看次数: |
2686 次 |
| 最近记录: |