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
Script via STDIN does not exit with error code and does not stop correctly #15331
Scordo I think a new parameter would be a better solution than making changes to how -Command - and -File - work today as someone else may be dependent on that behavior. So it seems the desire is to have a -Stdin switch that reads the entirety of stdin and executes as a single script rather than line by line and have a non-zero exit code if $? is $false indicating an error happened?
Yes -stdin as a new parameter would be fine. It should behave exactly the same as when running a .ps1 file. Respecting $ErrorActionPreference and so on. It would be perfect if we could also pass parameters to the script that was provided via `-stdin.
Steve Lee (@SteveL-MSFT), the current behavior of -Command - and especially -File - is unlikely to be relied upon in code with long-term stability concerns - it isn't suited to robust scripting.
Therefore, let me suggest we consider fixing the existing parameters an acceptable bucket 3: Unlikely Grey Area breaking change.
To minimize the impact, fixing -File - to work as Scordo describes would be sufficient - though I suggest including argument support while we're at it (-Command - has no counterpart in POSIX-compatible shells; - as the (positionally implied) script file name treats stdin input as if it were the content of a script).
Conversely, a -Stdin parameter would not only be nonstandard (not aligned with POSIX-compatible shells), but add to the already sizable number of parameters.
I think in this case, you could use a trap statement - here's an example of something that may serve you.
PS /> echo "trap { write-host `$_; exit 2 } `$ErrorActionPreference = 'stop';get-date;just bogus;get-location" | pwsh -nopro -command -
Friday, April 30, 2021 12:57:55 PM
The term 'just' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
PS /> $LASTEXITCODE
2
or a more complicated example:
PS /> echo "trap { write-host `$_;if ( `$ErrorActionPreference -eq 'continue') {continue}else{exit 2} } `$ErrorActionPreference = 'continue';get-date;just bogus;get-location" | pwsh -nopro -command -
Friday, April 30, 2021 12:59:53 PM
The term 'just' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Drive : /
Provider : Microsoft.PowerShell.Core\FileSystem
ProviderPath : /
Path : /
PS /> $LASTEXITCODE
0
The Enter-AzShell cmdlet from the powershell sub kernel in .NET Interactive depends on the current behavior of -File -. It depends on the behavior that -File - prints the prompt to detect the end of a command line execution.
There may be other uses that depend on the current behavior of -command - and -file -, so I think we should keep it unchanged and adding new syntax for reading the whole stdin content as file content. Maybe -file --?
(On a technicality, I claim that the silence promised in #10238 (comment), doesn't take effect until after 11:59:59 PM US EDT.)
While I can appreciate your due diligence here, what you're pointing out here is evidence of a fundamentally broken culture:
A different department in the same company decided to release an official feature based on working around obviously broken/useless behavior in a product released by a different department in the same company - rather than seeking a shared understanding and joint resolution.
This will encapsulate the command you want to run as 1 scriptblock and execute that rather than each statement as 1 line.
This might work for small scripts, but if one is running 3rd-party scripts (such as in a CI solution), there's no telling how long those lines could become, so this doesn't seem like an all-round solution.
I wouldn't say it's completely unusable there are workarounds that make this entirely possible. The method I usually use is this
docker run \
--rm \
--interactive \
mcr.microsoft.com/powershell pwsh -Command - << 'EOF'& { if ($true) { echo "hi" }}EOF
Basically make sure there is an empty line between `}` and `EOF` so the input is accepted by pwsh and also put all your code inside a `&{}` block to ensure it is run as 1 script rather than the line by line parser that is the standard console input code.
That's fine for when I'm the one launching the image. The real issue is when I'm trying to use GitLab's pipeline features where I don't really have control over how they launch the image and inject the script. I just get to add lines to a script tag in a yaml file that gets executed by a runner.
Here's what I came up with: type Test.ps1 | pwsh -NoP -c "$code=$Input|&{process{$_}};[ScriptBlock]::Create($code-join[char]10).Invoke()"
And a longer alternative that avoids having to use [char]10: type Test.ps1 | pwsh -NoP -c "$code=[Text.StringBuilder]'';$Input|&{process{$null=$code.AppendLine($_)}};[ScriptBlock]::Create($code.ToString()).Invoke()"
If you want to have an argument, set an environmental variable to something like ARG and call Invoke like this: .Invoke($env:ARG)
Or if you have multiple arguments, ARG1 and ARG2, calling .Invoke like this: .Invoke($env:ARG1,$env:ARG2)
You could also put a long string into an env variable with some sort of separator and then call .Split(seperator) or use -split seperator within Invoke
Michael Klement (@mklement0) I understand the desire to fix the behavior of -file - to align with precedent of other shells, but given the examples of using it as a REPL, it seems less likely to be a bucket 3 item.
I think the best solution at this time is to document the workaround as the supported way to have a multi-line script executed at once vs line-by-line. This would work on all versions of PowerShell whereas a new switch would only work on the latest while the workaround can still be used anyways.
Steve Lee (@SteveL-MSFT) Do you mind summarizing what the recommended way to handle this is? There have been a few suggestions in this thread so far, but it's not entirely clear to me what the right way to proceed is.
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commented on Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commented on Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
Activity
mklement0 commentedon Apr 30, 2021
Good catch.
Unfortunately
-Command -(and-File -too) have fundamental problems: #3223It is the line-by-line (statement-by-statement) execution described in the linked issue that explains the behavior.
Scordo commentedon Apr 30, 2021
Maybe you should introduce new parameters in 7.2 to fix the issues and remain compatible to all the usages living with the current buggy behavior.
SteveL-MSFT commentedon Apr 30, 2021
Scordo I think a new parameter would be a better solution than making changes to how
-Command -and-File -work today as someone else may be dependent on that behavior. So it seems the desire is to have a-Stdinswitch that reads the entirety of stdin and executes as a single script rather than line by line and have a non-zero exit code if$?is $false indicating an error happened?Scordo commentedon Apr 30, 2021
Yes
-stdinas a new parameter would be fine. It should behave exactly the same as when running a .ps1 file. Respecting $ErrorActionPreference and so on. It would be perfect if we could also pass parameters to the script that was provided via `-stdin.mklement0 commentedon Apr 30, 2021
Steve Lee (@SteveL-MSFT), the current behavior of
-Command -and especially-File -is unlikely to be relied upon in code with long-term stability concerns - it isn't suited to robust scripting.Therefore, let me suggest we consider fixing the existing parameters an acceptable bucket 3: Unlikely Grey Area breaking change.
To minimize the impact, fixing
-File -to work as Scordo describes would be sufficient - though I suggest including argument support while we're at it (-Command -has no counterpart in POSIX-compatible shells;-as the (positionally implied) script file name treats stdin input as if it were the content of a script).Conversely, a
-Stdinparameter would not only be nonstandard (not aligned with POSIX-compatible shells), but add to the already sizable number of parameters.JamesWTruher commentedon Apr 30, 2021
I think in this case, you could use a trap statement - here's an example of something that may serve you.
or a more complicated example:
jborean93 commentedon Apr 30, 2021
You could also try running it in it's own scriptblock like the following.
This will encapsulate the command you want to run as 1 scriptblock and execute that rather than each statement as 1 line.
daxian-dbw commentedon Apr 30, 2021
The
Enter-AzShellcmdlet from the powershell sub kernel in .NET Interactive depends on the current behavior of-File -. It depends on the behavior that-File -prints the prompt to detect the end of a command line execution.There may be other uses that depend on the current behavior of
-command -and-file -, so I think we should keep it unchanged and adding new syntax for reading the whole stdin content as file content. Maybe-file --?mklement0 commentedon May 1, 2021
Dongbo Wang (@daxian-dbw):
(On a technicality, I claim that the silence promised in #10238 (comment), doesn't take effect until after 11:59:59 PM US EDT.)
While I can appreciate your due diligence here, what you're pointing out here is evidence of a fundamentally broken culture:
A different department in the same company decided to release an official feature based on working around obviously broken/useless behavior in a product released by a different department in the same company - rather than seeking a shared understanding and joint resolution.
pedropombeiro commentedon May 1, 2021
This might work for small scripts, but if one is running 3rd-party scripts (such as in a CI solution), there's no telling how long those lines could become, so this doesn't seem like an all-round solution.
11 remaining items
FaustinCarter commentedon Jan 19, 2022
Is there any movement on this? This is making using pwsh on docker containers in Gitlab completely unusable.
jborean93 commentedon Jan 19, 2022
I wouldn't say it's completely unusable there are workarounds that make this entirely possible. The method I usually use is this
FaustinCarter commentedon Jan 20, 2022
That's fine for when I'm the one launching the image. The real issue is when I'm trying to use GitLab's pipeline features where I don't really have control over how they launch the image and inject the script. I just get to add lines to a script tag in a yaml file that gets executed by a runner.
God-damnit-all commentedon Nov 25, 2022
Here's what I came up with:
type Test.ps1 | pwsh -NoP -c "$code=$Input|&{process{$_}};[ScriptBlock]::Create($code-join[char]10).Invoke()"And a longer alternative that avoids having to use [char]10:
type Test.ps1 | pwsh -NoP -c "$code=[Text.StringBuilder]'';$Input|&{process{$null=$code.AppendLine($_)}};[ScriptBlock]::Create($code.ToString()).Invoke()"If you want to have an argument, set an environmental variable to something like ARG and call Invoke like this:
.Invoke($env:ARG)Or if you have multiple arguments, ARG1 and ARG2, calling
.Invokelike this:.Invoke($env:ARG1,$env:ARG2)You could also put a long string into an env variable with some sort of separator and then call
.Split(seperator)or use-split seperatorwithinInvokeSteveL-MSFT commentedon Nov 28, 2022
Michael Klement (@mklement0) I understand the desire to fix the behavior of
-file -to align with precedent of other shells, but given the examples of using it as a REPL, it seems less likely to be a bucket 3 item.I think the best solution at this time is to document the workaround as the supported way to have a multi-line script executed at once vs line-by-line. This would work on all versions of PowerShell whereas a new switch would only work on the latest while the workaround can still be used anyways.
FaustinCarter commentedon Nov 29, 2022
Steve Lee (@SteveL-MSFT) Do you mind summarizing what the recommended way to handle this is? There have been a few suggestions in this thread so far, but it's not entirely clear to me what the right way to proceed is.
SteveL-MSFT commentedon Dec 5, 2022
Faustin Carter (@FaustinCarter) I think the best practice would be to have the script in a
.ps1and execute it that way instead of using STDIN. Jordan Borean (@jborean93) has a viable workaround #15331 (comment) for cases where you can't write to a temporary.ps1God-damnit-all commentedon Dec 5, 2022
It's a great stop-gap solution for what I hope will only be a temporary problem.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 23, 2023
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.