You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CLI: pwsh -Command - and pwsh -File - unexpectedly exhibit pseudo-interactive behavior, lack support for argument passing #3223
While pwsh -Command - and pwsh -File - both accept command input from the pipeline / from stdin:
they exhibit undesirable pseudo-interactive behavior:
they execute each line one by one, in separate pipelines.
additionally, -File - prints the prompt string and each input line before the output
they require pipelines that are spread across multiple lines for readability to be terminated with two newlines (see below) - as would be necessary interactively, if PSReadLine weren't loaded.
they do not support combining - input with passing arguments:
While that limitation is documented for -Command - (-File - is undocumented altogether), there's no good reason for this limitation, and it limits the usefulness of the construct.
While you could (but in my mind shouldn't) argue that -Command - should be limited to providing a self-contained source-code snippet that doesn't expect arguments, at the least -File - should support passing arguments by placing them after the - - after all, you want to be able to pass arguments to a script - whether that script is specified as a a file or as a script's content via stdin.
Thus, the following command, which spreads pipeline "hi" | % { "$_ there" } across two lines - does not work:
The above now yields in, hi there and out - that is, the multi-line pipeline was correctly submitted due to the extra newline, as was the single-line statement afterwards.
Summary:
Both File - and -Command - should be fixed; and, on Unix /dev/stdin should be the same as passing -.
If -File - worked properly, there'd really be no need for -Command -.
changed the title [-]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line and/or consider proper support for `-File -`[/-][+]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for `-File -`[/+]on Feb 27, 2017
changed the title [-]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for `-File -`[/-][+]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/+]on Feb 27, 2017
changed the title [-]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/-][+]CLI: Reconsider the behavior of pwsh -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/+]on Feb 2, 2019
changed the title [-]CLI: Reconsider the behavior of pwsh -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/-][+]CLI: `pwsh -Command -` and `pwsh -File -` unexpectedly exhibit pseudo-interactive behavior, lack support for argument passing[/+]on Apr 25, 2019
At first look I'd expect that "-Command -" accept only one line command but how input multi-line one? And it is not clear that is semantic of "-File script.ps1 -"
Also I'd expect that we read console input if there is not explicit redirection but currenly the dash accepted as argument that can confuse.
At first look I'd expect that -Command - accept only one line command but how input multi-line one?
As argued in #9494 (comment), there's really no point in supporting -Command - altogether, if -File - worked properly.
Given that we cannot remove it: Just like you can already pass a multi-line argument to -Command, the entirety of stdin input should be executed as a snippet of source code.
(Line-by-line interactive execution doesn't really make sense - just start a PowerShell session normally to do that.)
it is not clear that is semantic of -File script.ps1 -
As stated in the linked comment, the - is not special at all in this case: since it follows a -File argument - script.ps1 - it is just a (positional) argument to pass to script.ps1; - is only special in lieu of a script-file argument.
Given that we cannot remove it: Just like you can already pass a multi-line argument to -Command, the entirety of stdin input should be executed as a snippet of source code.
We have API Powershell.AddCommand() and Powershell.AddScript() - I believe "-Command" behavior must fit first and "-File" - second.
.AddScript() is the one that behaves like -Command - you can pass it an arbitrary snippet of PowerShell code - the method is poorly named, .AddScriptBlock() would have made more sense.
.AddCommand() is for adding a command name or path, with the need to specify arguments separately; as such it is akin to -File.
Aside from that, there's no requirement of one-to-one mapping to SDK methods here.
As shown, the names of the SDK methods not only do not align with the CLI parameters, but suggest the opposite mapping.
It is the CLI parameters that are sensibly named, and their fundamental semantics must not and should not change (-File is self-describing (the fact that the argument must be a script file is implied), and -Command / -c aligns with the long-established -c command in POSIX-like shells (and is akin to /c in cmd.exe)).
What should change, however, is how they deal with stdin input, as (now) suggested in the OP and argued in #9494 (comment)
P.S., Ilya (@iSazonov): You could open a separate issue suggesting more sensible alias names for the SDK methods (obviously, the old names cannot be removed); especially .AddScript() keeps causing confusion.
-File - is not documented so we could change its behavior as we need.
That's a good point.
We can then deprecate -Command - (and leave it as is) to support the following idioms, mostly based on -File, in conjunction with fixing #9497:
# Execute *code* piped from stdin.
...| pwsh # same as: ... | pwsh -File -# Execute *code* piped from stdin *with arguments* # (`File -` is then required for disambiguation)
...| pwsh -File - args...
# Provide *input data* via stdin - to a script file
...| pwsh -File someScript.ps1 [args...]
# Provide *input data* via stdin - to a string containing commands
...| pwsh -Command $snippetOfPsCode
The unfortunate thing - which we cannot change - is that -Command doesn't accept arguments to pass to $snippetOfPsCode (which the latter would see as $Args or bind to its parameters) - it simply considers the remaining arguments to be part of the command string.
I think this is a dead proposal (add aliases) because it is a public API.
I don't think it's a pressing issue, and the downside is that it bloats the SDK, but why couldn't we add new, more descriptive method names that effectively call their less descriptively named predecessors? Of course, you'd then need to know what version of the SDK you're targeting.
This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.
Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.
While the need for the extra line feed is suboptimal, I do want to point out that the interactive, block-at-a-time nature of -Command - is actually useful if you want to avoid PowerShell startup times to run multiple PS commands from a long-running process written in another language. Just open a pipe, feed it commands and read all the output, repeat as needed. Works like a charm for things you don't want to have to write in PowerShell, and don't want to have to wait an entire second for the executable to load up to run each command. It's like having a PowerShell DLL you can load from any language using only that language's subprocess piping capabilities.
So there are downsides to removing block-at-a-time execution - mainly that it's nearly impossible to do this in a practical manner when using actually-interactive PS, which echoes your input and spits out intermediate results you don't care about along with the final result you're looking for. -Command - neatly solves this.
This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.
Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.
Activity
[-]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line and/or consider proper support for `-File -`[/-][+]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for `-File -`[/+][-]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for `-File -`[/-][+]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/+][-]Reconsider the behavior of powershell.exe -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/-][+]CLI: Reconsider the behavior of pwsh -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/+][-]CLI: Reconsider the behavior of pwsh -Command -: it shouldn't require terminating multi-line commands with an empty line, and/or consider proper support for -File -[/-][+]CLI: `pwsh -Command -` and `pwsh -File -` unexpectedly exhibit pseudo-interactive behavior, lack support for argument passing[/+]iSazonov commentedon Apr 29, 2019
At first look I'd expect that "-Command -" accept only one line command but how input multi-line one? And it is not clear that is semantic of "-File script.ps1 -"
Also I'd expect that we read console input if there is not explicit redirection but currenly the dash accepted as argument that can confuse.
mklement0 commentedon Apr 29, 2019
As argued in #9494 (comment), there's really no point in supporting
-Command -altogether, if-File -worked properly.Given that we cannot remove it: Just like you can already pass a multi-line argument to
-Command, the entirety of stdin input should be executed as a snippet of source code.(Line-by-line interactive execution doesn't really make sense - just start a PowerShell session normally to do that.)
As stated in the linked comment, the
-is not special at all in this case: since it follows a-Fileargument -script.ps1- it is just a (positional) argument to pass toscript.ps1;-is only special in lieu of a script-file argument.iSazonov commentedon Apr 29, 2019
We have API
Powershell.AddCommand()and Powershell.AddScript() - I believe "-Command" behavior must fit first and "-File" - second.mklement0 commentedon Apr 29, 2019
It is the other way around:
.AddScript()is the one that behaves like-Command- you can pass it an arbitrary snippet of PowerShell code - the method is poorly named,.AddScriptBlock()would have made more sense..AddCommand()is for adding a command name or path, with the need to specify arguments separately; as such it is akin to-File.Aside from that, there's no requirement of one-to-one mapping to SDK methods here.
iSazonov commentedon Apr 29, 2019
My comment was about expected behavior. Both methods is often used in our tests and I'd expect such behavior in CLI too.
mklement0 commentedon Apr 29, 2019
As shown, the names of the SDK methods not only do not align with the CLI parameters, but suggest the opposite mapping.
It is the CLI parameters that are sensibly named, and their fundamental semantics must not and should not change (
-Fileis self-describing (the fact that the argument must be a script file is implied), and-Command/-caligns with the long-established-ccommand in POSIX-like shells (and is akin to/cincmd.exe)).What should change, however, is how they deal with stdin input, as (now) suggested in the OP and argued in #9494 (comment)
mklement0 commentedon Apr 29, 2019
P.S., Ilya (@iSazonov): You could open a separate issue suggesting more sensible alias names for the SDK methods (obviously, the old names cannot be removed); especially
.AddScript()keeps causing confusion.iSazonov commentedon Apr 30, 2019
Michael Klement (@mklement0) I think this is a dead proposal (add aliases) because it is a public API.
-File - is not documented so we could change its behavior as we need.
mklement0 commentedon Apr 30, 2019
That's a good point.
We can then deprecate
-Command -(and leave it as is) to support the following idioms, mostly based on-File, in conjunction with fixing #9497:The unfortunate thing - which we cannot change - is that
-Commanddoesn't accept arguments to pass to$snippetOfPsCode(which the latter would see as$Argsor bind to its parameters) - it simply considers the remaining arguments to be part of the command string.I don't think it's a pressing issue, and the downside is that it bloats the SDK, but why couldn't we add new, more descriptive method names that effectively call their less descriptively named predecessors? Of course, you'd then need to know what version of the SDK you're targeting.
5 remaining items
Veetaha commentedon Mar 22, 2024
Nice joke. It is still relevant
Veetaha commentedon Nov 6, 2024
Bruh. Fix this issue already please
pjeby commentedon Jan 5, 2025
While the need for the extra line feed is suboptimal, I do want to point out that the interactive, block-at-a-time nature of
-Command -is actually useful if you want to avoid PowerShell startup times to run multiple PS commands from a long-running process written in another language. Just open a pipe, feed it commands and read all the output, repeat as needed. Works like a charm for things you don't want to have to write in PowerShell, and don't want to have to wait an entire second for the executable to load up to run each command. It's like having a PowerShell DLL you can load from any language using only that language's subprocess piping capabilities.So there are downsides to removing block-at-a-time execution - mainly that it's nearly impossible to do this in a practical manner when using actually-interactive PS, which echoes your input and spits out intermediate results you don't care about along with the final result you're looking for.
-Command -neatly solves this.Veetaha commentedon Jul 5, 2025
Nah-ah
microsoft-github-policy-service commentedon Jan 2, 2026
This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.
Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.
xtqqczze commentedon Jan 13, 2026
Ilya (@iSazonov) Please reopen.
feat(exec): PowerShell side-channel result transport