让我们从正常行为开始。当我在没有提示的情况下执行Read-Host
时,我可以输入以感叹号开头的字符串:
PS C:\> Read-Host | Foreach-Object { Write-Host 'Entered' $_ }
!hi, mom
Entered !hi, mom
(请注意,我只管道Foreach-Object
作为输出前缀的简单方法。如果你在没有它的情况下执行Read-Host
,感兴趣的行为是相同的。)
但如果我给Read-Host
一个提示参数,那么行为就完全不同了:
PS C:\> Read-Host 'Enter something' | Foreach-Object { Write-Host 'Entered' $_ }
Enter something: !hi, mom
"!hi, mom" cannot be recognized as a valid Prompt command.
Enter something: !!hi, mom
Entered !hi, mom
似乎感叹号允许我除了输入一个字符串之外还做一些事情。 PowerShell正在解释感叹号意味着我正在输入某种命令让它运行,但我找不到任何关于允许的内容的文档。除了将感叹号加倍以逃避它之外,我无法弄清楚是是一个有效的命令。
请注意,输入必须开始并带有感叹号。结束它不会触发此行为:
PS C:\> Read-Host 'Enter something' | Foreach-Object { Write-Host 'Entered' $_ }
Enter something: hi, mom!
Entered hi, mom!
那么我可以在这里使用!
做什么?什么是一个有效的命令,除了逃避感叹号?解决方法很有用,但我实际上想知道我是否可以在这里执行代码。
我正在使用PowerShell 4,但这似乎更早date back。
答案 0 :(得分:6)
<强> TL;博士强>
Read-Host
,顾名思义,是特定于主机的。
Read-Host
提示符,但没有受到影响。该行为实际上是 无关的功能,似乎意外暴露,即{strong> 仅 {{1}指定了提示字符串参数(Read-Host
)。
解决错误,如下所示:
-Prompt
Write-Host -NoNewline 'Enter something: '; Read-Host
分别打印提示字符串,预先(没有换行符),然后调用Write-Host
而不用 { {1}}参数:要回答问题的标题,&#34;我该怎么办!什么时候使用Read-Host?&#34;:什么都没用 要了解原因和背景信息,请继续阅读。
行为 - 以及对它的抱怨 - 可以追溯到PowerShell的第一个版本;在post also linked to by the OP,MS员工称之为&#34;提示命令&#34; ,其中一位架构师更详细地解释了here @TheMadTechnician在评论问题
请注意,在PowerShell 本身如何提示缺少必需参数值 的上下文中讨论,其中 应该< / em>与Read-Host
:
当系统提示您输入未在命令行中指定的必需参数值时(以及使用-Prompt
值Read-Host
时也出乎意料),Read-Host
为< em>第一个字符(仅)启动&#34;提示命令&#34;:
-Prompt
为手头参数(描述)调用帮助字符串。
!
的上下文中,提示字符串(!)被解释为寻求帮助的参数名称,因此找不到帮助(!?
)。 Read-Host
允许输入空字符串作为数组参数的参数值,同时允许输入其他值(只需按Enter键即可终止提示)。
No help is available for <prompt-string>
的上下文中,这只是输出一个空字符串。 !""
允许输入文字 Read-Host
Χpẘ's great answer使用基础程序集的反汇编来表明,至少从PS v3开始,不支持其他命令。
linked forum post得出结论(强调我的):
请注意,这是当前实现的工件 在PowerShell主机中提示。它不是核心引擎的一部分。一个 GUI主机不太可能使用此表示法。一个合理 增强功能是允许提示命令 用户可配置的强>
10年后,行为 - 至少在!!
的背景下 - 既没有记录也没有可配置。
在发现上述帖子之前,jpmc26自己发现该行为与PowerShell 本身如何提示缺少必需参数有关; e.g:
!
答案 1 :(得分:3)
使用JetBrains dotPeek我找到了'!'的实现被处理。它位于程序集Microsoft.PowerShell.ConsoleHostUserInterface.PromptCommandMode
中的Microsoft.Powershell.ConsoleHost
中。这是PS 3.0。反汇编的代码如下。
strA.StartsWith
的检查必须是查看'!'被另一个'!'逃脱了。
请注意,检查strA[0] == 63
是否检查'?' (0x3F的)。任何其他单个字符输入都会在OP中产生错误消息。两个双引号产生空字符串(这是Bruce Payette在OP注释中引用的链接中所说的),字符串'$null'
产生$null
。
其他任何内容都会显示相同的错误消息。因此,如果没有某种代理或写主持人,'!'不能真正用于其他命令。
private string PromptCommandMode(string input, FieldDescription desc, out bool inputDone)
{
string strA = input.Substring(1);
inputDone = true;
if (strA.StartsWith("!", StringComparison.OrdinalIgnoreCase))
return strA;
if (strA.Length == 1)
{
if ((int) strA[0] == 63)
{
if (string.IsNullOrEmpty(desc.HelpMessage))
{
string str = StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptNoHelpAvailableErrorTemplate, (object) desc.Name);
ConsoleHostUserInterface.tracer.TraceWarning(str);
this.WriteLineToConsole(this.WrapToCurrentWindowWidth(str));
}
else
this.WriteLineToConsole(this.WrapToCurrentWindowWidth(desc.HelpMessage));
}
else
this.ReportUnrecognizedPromptCommand(input);
inputDone = false;
return (string) null;
}
if (strA.Length == 2 && string.Compare(strA, "\"\"", StringComparison.OrdinalIgnoreCase) == 0)
return string.Empty;
if (string.Compare(strA, "$null", StringComparison.OrdinalIgnoreCase) == 0)
return (string) null;
this.ReportUnrecognizedPromptCommand(input);
inputDone = false;
return (string) null;
}
private void ReportUnrecognizedPromptCommand(string command)
{
this.WriteLineToConsole(this.WrapToCurrentWindowWidth(StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptUnrecognizedCommandErrorTemplate, (object) command)));
}
答案 2 :(得分:2)
这是拼图的另一部分 我正在运行V5,它可以在ISE中运行:
PS C:\> $PSVersionTable
Name Value
---- -----
PSVersion 5.0.10586.51
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.10586.51
CLRVersion 4.0.30319.34209
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
PS C:\> Read-Host 'Enter something' | Foreach-Object { Write-Host 'Entered' $_}
Enter something: !Hi, mom
Entered !Hi, mom
但它无法在正常的命令提示符下运行:
PS C:\> Read-Host 'Enter something' | Foreach-Object { Write-Host "Entered $_"}
Enter something: !Hi, mom
"!Hi, mom" cannot be recognized as a valid Prompt command.
Enter something: