Skip to content

Call native operator #13068

Closed
Closed
@SteveL-MSFT

Description

@SteveL-MSFT

Problem Statement

Currently, there are cases where cutting and pasting a native command line fails to run as expected in PowerShell. This may be due to incorrect parsing of quotes meant to be passed to the native command or use of PowerShell syntax that is not meant to be interpreted as PowerShell. PowerShell has a --% special argument when used with native commands treats the rest of the arguments as literals passed to the native command, but has several issues:

  1. It is not discoverable, users need to know about this special parameter ahead of time
  2. |, &&, and || take precedence, so: wsl --% ls | less would execute wsl ls and pipe the results to less running in PowerShell rather than less running in wsl
  3. If you cut and paste a command line, you would need to edit the line to insert --% towards the beginning
  4. On Unix systems, the args after --% are passed verbatim w/o globbing where native commands on Unix expect the shell to perform globbing

Proposed technical implementation details

Proposal is to introduce a new --% (Call Native) operator.

Any text content after this operator will call into the "default shell" of the OS to execute. On Windows, this would be cmd.exe and on Unix-based systems this would be /bin/sh. This resolves the globbing issue on Unix-based systems, and also allow %variable% expansion on Windows. Unlike --% switch, this also means that |, &&, and || are treated as part of the native command line.

This means that these two are functionally the same:

wsl --% ls $foo `&`& echo $PWD
--% wsl ls $foo && echo $PWD

where $foo and $PWD is evaluated by the shell within WSL. Note that in the first example, you would have to know to escape && to have it execute within WSL instead of within PowerShell.

To pipe output from such execution back into PowerShell, the user is required to store the results into a variable first:

$out = --% ls *.txt
$out | select-string hello

Note that unlike the current & call operator, you cannot use any PowerShell syntax, so:

--% $commandline

would not resolve $commandline as a variable first by PowerShell, but instead pass $commandline to the default shell to process unresolved.

The cut & paste problem is solved by simply pasting after --% is typed.

The above example for wsl would look like:

--% wsl ls | less

where the intent is to have that whole line execute within the WSL Linux instance.

Discoverability

Users already familiar with --% as a switch may easily transition to using this new operator where it makes sense. For new users, --% is unique so that search engines find it easily related to PowerShell.

Alternate Considerations

&! and &n were proposed as the sigil, but there was push back because &! is a valid operator in some languages making a web search for documentation more difficult. There was also a concern whether visual similar to & call operator would be confusing to users.

There is question about supporting line-continuation when using this new operator. I would suggest that we do not support it initially.

A cmdlet solution instead of an operator solution was proposed. We believe this doesn't solve the "cut & paste" problem as now you need to know to put the pipeline in single quotes and/or escape special characters. We do believe a cmdlet as in Invoke-NativeCommand (noun to be determined) would be useful as an additional option instead of replacing the need for an operator.

Related issues

This should also solve these issues:

#12491
#1761

Metadata

Metadata

Assignees

No one assigned

    Labels

    Committee-ReviewedPS-Committee has reviewed this and made a decisionIssue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifIssue-Enhancementthe issue is more of a feature request than a bugKeepOpenThe bot will ignore these and not auto-closeResolution-No ActivityIssue has had no activity for 6 months or more

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions