New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce a new cmdlet for calls to native (external) programs #18991
Comments
I don't really understand the technicalities of this issue, but would the situation be helped if this were possible: If the arguments require variables, they could be 'fed' to cmd via 'HKCU\Software\Microsoft\Command Processor\AutoRun'. |
|
I'd prefer aliases to be in the format v-n or v-nn. So i-nc in this case. |
Aliases were designed to mimic usual OS commands. There are no OS commands in that style. |
@Andrew74L, you can directly call As such, if This is what the |
As for the alias-name discussion:
In my view, such aliases - named for a different shell's internal commands (e.g., They are to be avoided for two reasons: given PowerShell's fundamentally different syntax, the user expectation that something like
This leaves us with PowerShell-idiomatic aliases, such as Any new aliases can conflict with existing utilities - the best we can do is avoid conflicts with standard utilities and well-known, widely used utilities. I don't think Of course, one option is not to ship with an alias at all and let users define their own, if desired. |
@mklement0, yes, but I was referring to your comment in the initial post...
Interesting. Would that require any modifications to cmd.exe?
I tried this...
Then this...
Very good! Although passing the command line 'as is', obviously didn't work, and this also works...
Why isn't something like the following possible...
Or is it? |
Your first attempt is a syntax error: you've neglected to escape the inner The second attempt is correct and the doubling of Leaving aside that Also note that you don't need In short: users will need to be aware that batch-file syntax is necessary, which affects |
For the first attempt I wasn't 'trying'. The point was to show that
Ah, yes.
Requiring the escaping of % chars. when used interactively, suggests that the cmdlet should be thought of as Invoke-Native_Script_. I associate 'shell' more with 'prompt' than 'script'. Aside from that pedantic note, I accept your points. |
You're passing a shell command line and that command line is a string, which means that you have to satisfy PowerShell's string-literal syntax rules; using a here-string can ease that pain: Invoke-NativeShell @'
for /F "skip=1 tokens=2" %%I in ('quser ^| find ">"') do @echo %%I
'@ You should never expect to be able to use a different shell's syntax as-is, unquoted in PowerShell. Any attempt to make this happen inevitably comes with severe limitations and/or obscure behavior. In fact, an attempt was made in v3+: The desire for such an inherently impossible solution - as understandable as that desire may be - gave rise to #13068. My summary of why I think such a pursuit is ultimately misguided is in #13068 (comment) (also linked to from the initial post).
I see your point, but (a) that a distinction needs to be made at all is a testament to Invoke-NativeCommand here, with a -UseShell switch - and all that is needed for the docs to make it clear that on Windows batch-file syntax applies.
Again, pragmatically speaking: For most made-for- |
For some reason I forgot about using a here-string. The problem remains as to how to get non-environmental variables into the string, as is the case with --%. To quote your SO post:
This is where I think HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun would be useful. The proposed new command could use the following sort of logic to 'pipe' (using that term loosely) variables to cmd.exe
Some details are omitted but you get the idea. |
No reason to use environment variables - just use an expandable, i.e. double-quoted version of a [here-string] literal to embed PowerShell variable and/or expression values. Invoke-NativeShell @"
@echo "`$PSHOME is: $PSHOME; `$(2 + 2) equals $(2 + 2)"
"@ |
That is more concise, but it also means mixing syntax and having to use escape characters.
|
Pragmatically speaking, That said, Invoke-NativeShell 'echo %1 %2' one two This would translate to ( Invoke-NativeComand -UseShell 'echo %1 %2' -ArgumentList one, two
# With -ArgumentList declared with ValueFromRemainingArguments
Invoke-NativeComand -UseShell 'echo %1 %2' one two Tangentially related:
|
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. |
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. |
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes. |
Summary of the new feature / enhancement
This supersedes the since-closed #18961, following a discussion with @jborean93 - see his summary.
Calls to native (external) programs are a recurring pain point:
There's the longstanding problem of broken handling of embedded double quotes, which the
$PSNativeCommandArgumentPassing
preference variable is meant to address.Even the new
Standard
mode cannot handle all edge cases, however, and sometimes direct control of the process command line is inevitable.Also, passing a full command line to the platform-native (legacy) shell is currently non-obvious and requires knowledge of the respective shell's CLI syntax.
There's the lack of integration with PowerShell's error handling, which the (still-experimental in v7.3.1)
PSNativeCommandUseErrorActionPreference
preference variable is meant to address.There's the problem of individual CLIs on Windows using character encoding that isn't aligned with the current code page /
[Console]::OutputEncoding
, such aspython
(ANSI encoding) andnode.exe
(UTF-8).While all these issues do have solutions, they are cumbersome, and especially ill-suited to per-call overrides of behavior configured via the preference variables.
A new cmdlet named, say,
Invoke-NativeCommand
(aliasinc
), could be introduced to ease that pain - see below.Related issues:
Proposed technical implementation details (optional)
Invoke-NativeCommand
/inc
should support the following:Behavior-modifying parameters:
-Encoding <encoding:
$OutputEncoding
and[Console]::OutputEncoding
with the specified encoding.-UseShell
- see above.-CommandLine
, optionally combined with-ArgumentList
/ remaining arguments.-CommandLine
(a single string) on Unix-like platforms.-ArgumentPassing <mode>
-ScriptBlock
$PSNativeCommandArgumentPassing
, where<mode>
may notably beLegacy
orStandard
-IgnoreExitCode
/-IgnoreExitCode:$false
$PSNativeCommandUseErrorActionPreference
robocopy.exe
-ErrorAction
parameter to override$PSNativeCommandUseErrorActionPreference
, withContinue
ignoring the exit code, andStop
throwing a script-terminating error in case of a nonzero exit code; the question then becomes whetherSilentlyContinue
andIgnore
should act differently fromContinue
and actually suppress stderr output (too), even though it is not the absence or presence of stderr output that constitutes an error (only the exit code does).-StandardErrorVariable <var-name>
-ErrorVariable
parameter, but exclusively applied to stderr output.-ErrorVariable
works, stderr output would still be passed through;2>$null
would silence it.-ErrorVariable
parameter to collect stderr output - even though stderr output isn't actually error output from PowerShell's perspective.The text was updated successfully, but these errors were encountered: