dea*_*dog 6 string powershell function start-process scriptblock
我有一个编辑注册表的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}"
Run Code Online (Sandbox Code Playgroud)
因此,在新的PowerShell流程中,它将首先在脚本块中定义代码,然后调用Test方法,并产生以下错误:
这:术语"This"不被识别为cmdlet,函数,脚本文件或可操作程序的名称.检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试.
所以它试图将字符串视为一个commad,就好像我刚刚This is a string在我的脚本中的新行上键入它一样.
如果我换行
$status = "This is a string"
Run Code Online (Sandbox Code Playgroud)
至
$status = 'This is a string'
Run Code Online (Sandbox Code Playgroud)
该脚本按预期工作,只是输出字符串This is a string.
我注意到的另一个奇怪的问题是,如果我不使用变量,只需使用:
Write-Output "This is a string"
Run Code Online (Sandbox Code Playgroud)
然后它在一个单独的行上输出每个单词,如下所示:
这个
是
一个
串
但如果我使用这样的单引号:
Write-Output 'This is a string'
Run Code Online (Sandbox Code Playgroud)
然后它按预期在一行输出整个句子.
有人知道为什么PowerShell在这些情况下会表现得很奇怪吗?
正如TessellatingHeckler所提到的,解决方案是用双引号,单引号包装任何双引号,或者你可以使用括号.
所以在我的例子中,你会改变:
$status = "This is a string"
Run Code Online (Sandbox Code Playgroud)
对此:
$status = """This is a string"""
Run Code Online (Sandbox Code Playgroud)
或这个:
$status = '"This is a string"'
Run Code Online (Sandbox Code Playgroud)
或这个:
$status = {"This is a string"}
Run Code Online (Sandbox Code Playgroud)
如果你想在你的字符串中评估一个变量(即看到变量的值),那么你必须使用双重双引号方法:
$status = """This is a string that evaluates $someVariable"""
Run Code Online (Sandbox Code Playgroud)
仍然不确定这是一个Bug还是设计,但至少我们有一个解决方法,因为这解决了我上面描述的两个问题.
如果我将你的脚本更改为
-Command $ScriptBlock
Run Code Online (Sandbox Code Playgroud)
运行它,让它打开一个新的 shell 窗口,然后运行
gci function:test | fl
Run Code Online (Sandbox Code Playgroud)
在新窗口中查看函数定义,显示的代码是
$status = This is a string
Run Code Online (Sandbox Code Playgroud)
对它显示的单引号版本进行相同的测试
$status = 'This is a string'
Run Code Online (Sandbox Code Playgroud)
所以它失去了双引号。用双引号转义它们
$status = """This is a string"""
Run Code Online (Sandbox Code Playgroud)
他们都顺利通过了。另外,即使脚本块是编译后的代码,在我看来,如果将它们扩展为字符串,它们就会作为文本嵌入:
> $s = { "hello" }
> "---$s---"
---"hello"---
Run Code Online (Sandbox Code Playgroud)
所以我认为你遇到了这种引用问题:PowerShell 从命令行参数中删除双引号,特别是Droj的回答,说“向外部程序发送参数的奇怪之处在于存在额外的引用评估级别。我不知道这是否是一个错误,但我猜它不会改变,因为当您使用 Start-Process 并传入参数时,行为是相同的。”。
PowerShell 将脚本块作为字符串扩展到命令中,然后字符串周围的单引号将被重新解释为带引号的参数,并在调用中的某处删除。这要么是已知问题,要么是错误,要么是设计使然,具体取决于您如何阅读该链接的连接文章。