让我们从正常行为开始.当我在Read-Host没有提示的情况下执行时,我可以输入以感叹号开头的字符串:
PS C:\> Read-Host | Foreach-Object { Write-Host 'Entered' $_ }
!hi, mom
Entered !hi, mom
Run Code Online (Sandbox Code Playgroud)
(请注意,我只是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
Run Code Online (Sandbox Code Playgroud)
似乎感叹号允许我做一些事情,只需输入一个字符串.PowerShell正在解释感叹号意味着我正在输入某种命令让它运行,但我找不到任何关于允许的内容的文档.除了将感叹号加倍以逃避它之外,我也无法弄清楚什么是有效命令.
请注意,输入必须以感叹号开头.使用它结束不会触发此行为:
PS C:\> Read-Host 'Enter something' | Foreach-Object { Write-Host 'Entered' $_ }
Enter something: hi, mom!
Entered hi, mom!
Run Code Online (Sandbox Code Playgroud)
那我该怎么办!呢?什么是有效的命令,除了逃避感叹号?解决方法很有用,但实际上我想知道我是否可以在这里执行代码.
我正在使用PowerShell 4,但这似乎可以追溯到更早.
TL;博士
Read-Host顾名思义,它是特定于主机的.
Read-Host提示,但没有受到影响).该行为是在效果的不相关的特征,其看似意外暴露,即只有当Read-Host的提示的字符串参数(-Prompt指定).
解决bug如下:
Write-Host -NoNewline 'Enter something: '; Read-HostWrite-Host分别打印的提示字符串,预先(不换行),然后调用Read-Host 而不的-Prompt参数:要回答问题的标题,"我能做什么!使用Read-Host时?":没什么用处.
要了解原因和背景信息,请继续阅读.
行为 - 以及对它的抱怨 - 可以追溯到PowerShell的第一个版本; 在该职位上也有一个MS员工将其称为"提示命令",其中一位建筑师在这里更详细地解释了@TheMadTechnician在评论中发现的问题.
需要注意的是是在PowerShell如何的背景下讨论本身提示缺少必需的参数值,这确实应该有不与关系Read-Host:
当提示输入(使用时和出乎意料地也即未在命令行上指定一个强制性的参数值Read-Host与一个-Prompt值),!作为第一个字符(只)启动一个"提示命令":
!? 为手头的参数(描述)调用帮助字符串.
Read-Host,提示字符串(!)被解释为寻求帮助的参数名称,因此找不到帮助(No help is available for <prompt-string>).!""允许输入空字符串作为数组参数的参数值,同时允许输入其他值(只需按Enter键即可立即终止提示).
Read-Host,这只是输出一个空字符串.!!允许输入文字 !
Χpẘ的好答案使用基础组件的反汇编来表明,至少从PS v3开始,不支持其他命令.
该链接的论坛发帖总结(重点煤矿):
请注意,这是PowerShell主机中当前提示实现的工件.它不是核心引擎的一部分.一个 GUI主机将不可能使用这个符号.一个合理的改进就是允许prompt命令是用户可配置的.
10年后,这种行为 - 至少在上下文中Read-Host- 既没有记录也没有可配置.
在发现上述帖子之前,jpmc26自己发现行为与PowerShell 本身如何提示缺少强制性参数有关 ; 例如:
# Define a test function with a mandatory parameter.
> function foo([Parameter(Mandatory=$true,HelpMessage='fooParam help')][string]$fooParam) {}
# Invoke the test function *without* that mandatory parameter,
# which causes Powershell to *prompt* for it.
> foo
cmdlet foo at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
fooParam: !? # !? asks for help on the parameter, which prints the HelpMessage attribute.
fooParam help
fooParam: # After having printed parameter help, the prompt is shown again.
Run Code Online (Sandbox Code Playgroud)
使用 JetBrains dotPeek 我找到了 where '!' 的实现 被处理。它在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)));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1742 次 |
| 最近记录: |