PowerShell: Parameter invalid when it contains a colon. Works prior to 7.3.0.
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
Enter:
$test = "&sqlcmd -v MDF_FILEPATH=```"C:\Databases\junk.mdf```""
invoke-expression $test
Expected behavior
sqlcmd is launched and you can enter:
select '$(MDF_FILEPATH)'
go
And be presented with:
----------------------------
C:\Databases\junk.mdf
Actual behavior
sqlcmd is no longer able to parse parameter value and you get the following after the invoke-expression:
Sqlcmd: 'MDF_FILEPATH=\"C:\Databases\junk.mdf\""': Invalid argument. Enter '-?' for help.
Error details
n/a
Environment data
Name Value
---- -----
PSVersion 7.3.0
PSEdition Core
GitCommitId 7.3.0
OS Microsoft Windows 10.0.22621
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Visuals
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 28 (20 by maintainers)
You can still do that without Invoke-Expression
You can also splat multiple arrays or use args inline with splats so you aren’t restricted to just this. Using
Invoke-Expression
is dangerous if the data comes from a user source and adds yet another layer you need to deal with when it comes to strings. It is best to try and avoid it in as many cases as you can.You need to quote the argument to avoid pwsh parameter binder from reading it differently
Hi,
we are facing the same problem with msbuild and property values containing a semicolon or comma. We have to support powershell 5.1 up to pwsh 7.3 and are using escaped quotes which are breaking in pwsh 7.3.
We dont want to set $PSNativeCommandArgumentPassing script-wide because it may cause incompatibilities when including 3rd party modules/scripts which dont expect this.
So we decided to go with local changes in scripts with the help of the following function:
Which we are using this way:
Hope this helps someone else.
@mklement0
testexe -echoargs
is used in tests, and the tests only expect the individual arguments, not extra texts for the raw command line. The-echoraw
flag is only for interactive use in cases like this one.@jborean93 Thank you for sharing the code! I submitted https://github.com/PowerShell/PowerShell/pull/18591 to update
testext
with a-echoraw
switch, to show the raw command line and the individual args. I think the existingtestexe -echoraw
is sufficient on Unix platforms, but let me know if that’s not the case.@daxian-dbw if it helps this is what I use to test out argv stuff on Windows
This unfortunately needs to run in WinPS but it can be run anywhere. It will output the raw command line value as well as the arguments as parsed by dotnet
Note I haven’t updated to 7.3.0 yet
For Linux I’ve also used the following before
You can compile it with
gcc print_argv.c -o print_argv
It is a bit more confusing there because Linux doesn’t have a command line string but uses
char *argv[]
.@daxian-dbw and @mklement0 This was an eye opening conversation. Thanks a ton for weighing in.
Indeed, a .NET (Core) application (as opposed to a .NET Framework application) does not report the true raw command line: see https://github.com/dotnet/runtime/issues/11305#issuecomment-674554010
@daxian-dbw I agree with @mklement0, the issue is unrelated to
Invoke-Expression
as I can recreate the problem without using it, and using the legacy workaround does allow the command to complete as before.Once we have the list updated and backported to 7.3.x, the idea is that you can keep
$PSNativeCommandArgumentPassing = 'Windows'
(which is the default) and commands in the list automatically uselegacy
when needed for compat. So you shouldn’t have to make any changes. However, if you usetlegacy
at the top of your script, then the changes we’re making should still not break you and you can keep it like that as well.