Start-Process powershell.exe
# or
Start-Process pwsh.exe
In the new window run the following
Add-Type -Namespace Kernel32 -Name NativeMethods -MemberDefinition @'
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr GetCommandLineW();
'@
$linePtr = [Kernel32.NativeMethods]::GetCommandLinew()
$cmdLine = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($linePtr)
"'{0}'" -f $cmdLine
'"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"'
# or
'"C:\Program Files\PowerShell\7\pwsh.exe"'
_Note: the path is dependent on where powershell is installed, this also affects v7_
'"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" '
# or
'"C:\Program Files\PowerShell\7\pwsh.exe" '
The actual command line contains a trailing space. If you were to start the process with arguments the trailing space comes after the arguments. This is not a problem when using System.Diagnostics.Process directly or the call operator.
Name Value
---- -----
PSVersion 5.1.17763.1007
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.17763.1007
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
# or
Name Value
---- -----
PSVersion 7.0.1
PSEdition Core
GitCommitId 7.0.1
OS Microsoft Windows 10.0.17763
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
After further testing, pwsh only has an issue when no arguments are supplied. WinPS has an issue even with the arguments but that's not really covered by this repo here. This is probably due to https://github.com/PowerShell/PowerShell/blob/58c371ca31d9e1b72da5d94821f2d670da5b4dfa/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs#L2003 which has a format string of "{0} {1}".
something to do with formatting, this happens only when wrapped in quotes "'$cmdLine'" just $cmdLine works as expected.
That鈥檚 because you can鈥檛 see the space without the single quotes around it. I only did that format string to easily demonstrate what is happening.
yep correct.
and it wont be from https://github.com/PowerShell/PowerShell/blob/58c371ca31d9e1b72da5d94821f2d670da5b4dfa/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs#L2003
targetMessage is displayed only when -WhatIf is used. This is from somewhere else.
Ah fair enough.
You may want to close https://github.com/PowerShell/PowerShell/issues/13097 as that鈥檚 a duplicate of this.
I believe the issue is in System.Diagnostics.Process as I see the same behavior that way and happens only if new windows is spawned.
I don't think so, when looking at the code PowerShell is actually calling CreateProcess here or CreateProcessWithLogon (if credentials were specified) here instead of using System.Diagnostics.Process to spawn the new process.
My guess as to what is happening is that the check for ArgumentList is true because while the ArgumentList is empty it is not null and the join operation is pretty much the same as ' ' -eq [string]::Join([String[]]@(), ' '). When the actual command line is being built it has a check on the argumentlist here. At this particular point in time arguments is equals to ' ' which is neither null or an empty string so it is appended to the command line to run. What I don't understand is why there's only 1 space, there should be 2 based on the assumption above. I don't have access to my dev environment so I can't step into the code to 100% check this but I don't think the issue lies in .NET but rather in PowerShell.
Sorry for the false alarm, just stepped through the code and I was wrong. By default Start-Process will use System.Diagnostics.Process unless other parameters are set which in this case it is not.
When running the code
$psi = [System.Diagnostics.ProcessStartInfo]@{
FileName = 'pwsh'
UseShellExecute = $true
}
[System.Diagnostics.Process]::Start($psi)
I see the same behaviour that Start-Process shows which indicates the problem is there and not in PowerShell. Even when forcing the code path to use the powershell call to CreateProcess by added -LoadUserProfile the command line args are fine.
My guess as to what is happening is that the check for ArgumentList is true because while the ArgumentList is empty it is not null and the join operation is pretty much the same as
' ' -eq [string]::Join([String[]]@(), ' ').
:-) Actually I was around this for hours with no luck and finally confirmed its in System.Diagnostics.Process by testing in that way...
Yea I should have listened to the experts :) thanks for your help.
Most helpful comment
Ah fair enough.
You may want to close https://github.com/PowerShell/PowerShell/issues/13097 as that鈥檚 a duplicate of this.