String PowerShell使用Start Process在脚本块内执行函数时会使用双引号执行一些奇怪的操作

String PowerShell使用Start Process在脚本块内执行函数时会使用双引号执行一些奇怪的操作,string,function,powershell,start-process,scriptblock,String,Function,Powershell,Start Process,Scriptblock,我有一个PowerShell脚本来编辑注册表,因此它需要以管理员身份运行。为此,我从正在运行的PowerShell脚本启动一个新的PowerShell进程,并使用一个包含函数的脚本块传入部分注册表项路径。当我在该函数中使用双引号时,PowerShell会尝试将它们解释为命令,而不是字符串。如果我使用单引号,那么一切都很好 我创建了一个简化的示例powershell脚本,它再现了这个问题。以下是片段: $ScriptBlock = { function Test {

我有一个PowerShell脚本来编辑注册表,因此它需要以管理员身份运行。为此,我从正在运行的PowerShell脚本启动一个新的PowerShell进程,并使用一个包含函数的脚本块传入部分注册表项路径。当我在该函数中使用双引号时,PowerShell会尝试将它们解释为命令,而不是字符串。如果我使用单引号,那么一切都很好

我创建了一个简化的示例powershell脚本,它再现了这个问题。以下是片段:

$ScriptBlock = {
    function Test
    {
        $status = "This is a string"
        Write-Output $status
    }
}
Start-Process -FilePath PowerShell -ArgumentList "-NoExit -NoProfile -ExecutionPolicy Bypass -Command & {$ScriptBlock Test}"
因此,在新的PowerShell进程中,它将首先在脚本块中定义代码,然后调用测试方法,并产生以下错误:

此:术语“This”不被识别为cmdlet的名称, 函数、脚本文件或可操作程序。检查单词的拼写 名称,或者如果包含路径,请验证该路径是否正确,并且 再试一次

因此,它试图将字符串视为逗号,就好像我刚刚在脚本的新行中键入了
这是一个字符串本身

如果我换线

$status = "This is a string"

脚本按预期工作,只输出字符串
,这是一个字符串

我注意到的另一个奇怪的问题是,如果我不使用变量,只使用:

Write-Output "This is a string"
然后,它在单独的行上输出每个单词,如下所示:

Write-Output 'This is a string'
这个

a

但如果我用这样的单引号:

Write-Output 'This is a string'
然后,它按预期在一行上输出整个句子

有人知道为什么PowerShell在这种情况下表现得很奇怪吗

答复 正如TessellingHeckler提到的,解决方案是将任何双引号、单引号或括号中的双引号括起来

在我的例子中,你会改变:

$status = "This is a string"
为此:

$status = """This is a string"""
或者这个:

$status = '"This is a string"'
$status = {"This is a string"}
或者这个:

$status = '"This is a string"'
$status = {"This is a string"}
如果要计算字符串中的变量(即查看变量的值),则必须使用双引号方法:

$status = """This is a string that evaluates $someVariable"""

仍然不确定这是一个Bug还是出于设计,但至少我们有一个解决方法,因为这可以解决我上面描述的两个问题。

如果我将您的脚本更改为

-Command $ScriptBlock
运行它,让它打开一个新的shell窗口,然后运行

gci function:test | fl 
要在新窗口中查看函数定义,显示的代码如下

$status = This is a string
在单报价版本上进行相同的测试

$status = 'This is a string'
所以它失去了双引号。用双引号将其转义

$status = """This is a string"""
他们都挺过来了。此外,即使脚本块是编译代码,但在我看来,如果将它们展开为字符串,它们也会作为文本嵌入:

> $s = { "hello" }
> "---$s---"
---"hello"---
所以我认为你遇到了这样一个引用问题:Droj的回答特别是“将参数发送到外部程序的奇怪之处在于,存在额外的报价评估级别。我不知道这是否是一个bug,但我猜它不会被更改,因为当您使用启动进程和传入参数时,行为是相同的。”

PowerShell正在将脚本块作为字符串扩展到您的命令中,然后字符串周围的单引号将被重新解释为带引号的参数,并在调用中的某个位置删除。这可能是一个已知问题,也可能是一个bug,也可能是由设计引起的,具体取决于您阅读链接的connect文章的方式