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-Expressionis 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 -echoargsis used in tests, and the tests only expect the individual arguments, not extra texts for the raw command line. The-echorawflag 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
testextwith a-echorawswitch, to show the raw command line and the individual args. I think the existingtestexe -echorawis 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_argvIt 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-Expressionas 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 uselegacywhen needed for compat. So you shouldn’t have to make any changes. However, if you usetlegacyat 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.