Skip to content

Using -Args with -Command does not work as documented #15410

Closed

Description

The powershell command line docs suggest that the "-Command" option may be used with the "-args" option to pass extra arguments to a script block. However, this does not work as described.

Recommend updating the command line documentation to document the actual behavior of -Command, which does not support an -args option.

Usage: pwsh[.exe] [-Login] [[-File] <filePath> [args]]
                  [-Command { - | <script-block> [-args <arg-array>]
                                | <string> [<CommandParameters>] } ]

Steps to reproduce

powershell.exe -Command "{ echo $args[1] }" -args one two three

Expected behavior

print two

Actual behavior

error:

aaronla@aaronla-r:scratch$ dotnet pwsh -command "{ echo $args[1] }" -args one two three
ParserError:
Line |
   1 |  { echo $args[1] } -args one two three
     |                    ~~~~~
     | Unexpected token '-args' in expression or statement.

Environment data

aaronla@aaronla-r:PowerApps-CoreServices$ dotnet pwsh -command echo $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.0.3
PSEdition                      Core
GitCommitId                    7.0.3
OS                             Microsoft Windows 10.0.19043
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Activity

  1. ghost added
    Needs-TriageThe issue is new and needs to be triaged by a work group.
    on May 14, 2021
  2. jhoneill commented on May 14, 2021

    @jhoneill

    The command needs to be written as a script block, not a string, and the args as an array

    pwsh -command { echo $args[1] } -args one,two,three

    When a string is used in place of the script block, -args isn't allowed ,but you can do something like

    pwsh -c "dir" "function:"

  3. vexx32 commented on May 15, 2021

    @vexx32
    Collaborator

    It works -- but it only works if the shell you're running it in is itself powershell/pwsh. The scriptblock handling that allows -Command to take an actual scriptblock requires that the shell handing the argument to the executable is powershell or pwsh, which will actively serialize the input to a format that the new shell instance can parse.

    Without that, everything following -Command is assumed to be a single command string/script, so -Args is never read as an executable argument, but interpreted as part of the command string.

  4. 237dmitry commented on May 15, 2021

    @237dmitry

    It works in bash:

    pwsh -c '{ echo $args.count; $args[0]; $args -join " "}.Invoke(1,2,3)'
    

    returned:

    3
    1
    1 2 3
    

    In my opinion the better way is to start executable (chmod +x) pwsh-scripts with shebang #!/usr/bin/pwsh -NoProfile

  5. jhoneill commented on May 15, 2021

    @jhoneill

    James O'Neill (@jhoneill) No dice for me. Similar error:
    I'd like something I can reasonably forward cmd's %* args through. E.g.

    REM example
    powershell.exe -command { & .\init.ps1; & .\myscript.ps1 @args } -args %*
    

    Obviously the above doesn't work. But how do you fix it?

    My brain is having trouble with writing a batch file that runs PowerShell (why not have everything in one PS script) but this works

    powershell -noprofile -command "echo %*"

  6. rjmholt commented on May 17, 2021

    @rjmholt
    Collaborator

    Sean Wheeler (@sdwheeler) are you able to transfer this to PowerShell-Docs?

  7. 237dmitry commented on May 17, 2021

    @237dmitry

    but I get a very similar error when run on bash

    It works, I think string arguments in .Invoke() should be in quotation marks:

    1_000

  8. rjmholt commented on May 17, 2021

    @rjmholt
    Collaborator

    If that's the intended behavior, that this feature only work from specific shells, then perhaps that's the scope of the bug. Update the documentation to reflect that this only works on bash and powershell, and not via exec / CreateProcess / batch / Windows command line.

    From about_powershell.exe:

    The Command parameter only accepts a script block for execution when it can recognize the value passed to Command as a ScriptBlock type. This is only possible when running powershell.exe from another PowerShell host. The ScriptBlock type may be contained in an existing variable, returned from an expression, or parsed by the PowerShell host as a literal script block enclosed in curly braces ({}), before being passed to powershell.exe.

    using the powershell function/alias

    It's working as the standard executable here, it's just that the invoking PowerShell process is able to translate the scriptblock passed as an argument into an encoded command under the hood.

  9. rjmholt commented on May 17, 2021

    @rjmholt
    Collaborator

    I propose updating the documentation

    Also please note that the repo for that is https://github.com/PowerShell/PowerShell-Docs.

    GitHub
    The official PowerShell documentation sources. Contribute to MicrosoftDocs/PowerShell-Docs development by creating an account on GitHub.
  10. sdwheeler commented on May 17, 2021

    @sdwheeler
    Contributor

    This works, as stated in the docs, when it is run from within a PowerShell session.

    PS> $PSVersionTable
    
    Name                           Value
    ----                           -----
    PSVersion                      7.1.3
    PSEdition                      Core
    GitCommitId                    7.1.3
    OS                             Microsoft Windows 10.0.19043
    Platform                       Win32NT
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
    PSRemotingProtocolVersion      2.3
    SerializationVersion           1.1.0.1
    WSManStackVersion              3.0
    
    PS> pwsh -command { echo $args[1] } -args one,two,three
    two
    PS> powershell -command { echo $args[1] } -args one,two,three
    two
    
    PS> $PSVersionTable
    
    Name                           Value
    ----                           -----
    PSVersion                      5.1.19041.906
    PSEdition                      Desktop
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
    BuildVersion                   10.0.19041.906
    CLRVersion                     4.0.30319.42000
    WSManStackVersion              3.0
    PSRemotingProtocolVersion      2.3
    SerializationVersion           1.1.0.1
    
    
    PS> powershell -command { echo $args[1] } -args one,two,three
    two
    PS> pwsh -command { echo $args[1] } -args one,two,three
    two
    PS>
    
  11. added and removed
    Needs-TriageThe issue is new and needs to be triaged by a work group.
    on May 17, 2021
  12. rjmholt commented on May 17, 2021

    @rjmholt
    Collaborator

    Given the discussion in the issue, I think the docs already cover this case and have marked it resolved. If there are changes you'd like to see in the documentation, please open an issue in https://github.com/MicrosoftDocs/PowerShell-Docs.

    GitHub
    The official PowerShell documentation sources. Contribute to MicrosoftDocs/PowerShell-Docs development by creating an account on GitHub.
  13. ghost closed this as completedon May 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions