PowerShell / vscode-powershell

Provides PowerShell language and debugging support for Visual Studio Code
https://marketplace.visualstudio.com/items/ms-vscode.PowerShell
MIT License
1.69k stars 479 forks source link

PowerShell Integrated Console: "Value cannot be null" for missing mandatory parameter when debugging #1969

Open gmckeown opened 5 years ago

gmckeown commented 5 years ago

Issue Type: Bug

Steps to reproduce

Create a .ps1 script file with the following contents:

class MyNewClass {
    [string] $DummyVar
}

function Get-Details {
    param (
        [Parameter(Mandatory)][MyNewClass] $ClassVar,
        [Parameter(Mandatory)][String] $StringVar
    )
    $ClassVar | Out-Host
}

Get-Details

Run the script from a PowerShell terminal window in VSCode.

Expected behavior

Using an explicit "pwsh" terminal inside VSCode, or an external Windows PowerShell or PowerShell Core shell, the above code gives:

cmdlet Get-Details at command pipeline position 1
Supply values for the following parameters:
ClassVar:

Actual behavior

From the PowerShell Integrated Console, the same script results in:

Value cannot be null.
Parameter name: type
At C:\Users\myuser\Documents\Development\PowerShell\TestParamNull.ps1:14 char:1
+ Get-Details
+ ~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (:) [], ArgumentNullException
+ FullyQualifiedErrorId : System.ArgumentNullException

If I explicitly call "pwsh" from inside this same integrated console, the script then works as expected.

Best guesses are that the issue is occurring when the debugger is involved, or that your readline is choking because it doesn't know how to request the user enters a custom class?

Environment data

Explicit pwsh

PS> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.2.0
PSEdition                      Core
GitCommitId                    6.2.0
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
PS> $PSHOME
C:\Program Files\PowerShell\6

PowerShell Integrated Console

PS>$PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.2.0
PSEdition                      Core
GitCommitId                    6.2.0
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
PS> $PSHOME
C:\Program Files\PowerShell\6

VSCode PowerShell Debugger Launch Config

        {
            "name": "PowerShell Launch Current File",
            "type": "PowerShell",
            "request": "launch",
            "script": "${file}",
            "args": [],
            "cwd": "${file}"
        }

Extension version: 1.12.1 VS Code version: Code 1.34.0 (a622c65b2c713c890fcf4fbf07cf34049d5fe758, 2019-05-15T21:59:37.030Z) OS version: Windows_NT x64 10.0.17763

System Info |Item|Value| |---|---| |CPUs|Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz (8 x 2904)| |GPU Status|2d_canvas: enabled
checker_imaging: disabled_off
flash_3d: enabled
flash_stage3d: enabled
flash_stage3d_baseline: enabled
gpu_compositing: enabled
multiple_raster_threads: enabled_on
native_gpu_memory_buffers: disabled_software
rasterization: enabled
surface_synchronization: enabled_on
video_decode: enabled
webgl: enabled
webgl2: enabled| |Load (avg)|undefined| |Memory (System)|31.81GB (14.95GB free)| |Process Argv|| |Screen Reader|no| |VM|0%|
rjmholt commented 5 years ago

Looks like this occurs when a class is used as a mandatory parameter like this

rjmholt commented 5 years ago

It's likely that this is fixed in the preview extension using PSReadLine

rjmholt commented 5 years ago

It's likely that this is fixed in the preview extension using PSReadLine

@TylerLeonhardt just confirmed that this does indeed work in the preview extension

gmckeown commented 5 years ago

Just installed a fresh copy of VSCode Insiders:

Version: 1.35.0-insider (user setup) Commit: a5536b8f5a16a10d859f3dec1e59701671bf069e Date: 2019-05-20T05:17:36.269Z Electron: 3.1.8 Chrome: 66.0.3359.181 Node.js: 10.2.0 V8: 6.6.346.32 OS: Windows_NT x64 10.0.17763

Then installed PowerShell preview 2.0.2

Placed the following into my settings.json:

{
    "terminal.integrated.shell.windows": "c:\\program files\\PowerShell\\6\\pwsh.exe",
    "powershell.powerShellExePath": "C:\\Program Files\\PowerShell\\6\\pwsh.exe"
}

Output was as it was before:

PS> .\TestParamNull.ps1
Value cannot be null.
Parameter name: type
At C:\Users\myuser\Documents\Development\PowerShell\TestParamNull.ps1:14 char:1
+ Get-Details
+ ~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (:) [], ArgumentNullException
+ FullyQualifiedErrorId : System.ArgumentNullException

Added this to my settings.json:

    "powershell.developer.featureFlags": [ "PSReadLine" ]

And now I get:

PS> .\TestParamNull.ps1

cmdlet Get-Details at command pipeline position 1
Supply values for the following parameters:
ClassVar:

So that does seem pretty conclusive! :)

ppainter1958 commented 4 years ago

Posting this, for what it's worth, for other poor schlubs like me who might stumble onto this expensive lesson. This Operation Stopped: Value cannot be null. (Parameter 'type') error happens when [ordered] is used as a type rather than an attribute. Of course, it is a total misuse of [ordered]. But it stumped me for a long time. I hope this saves someone some pain.

Wrong way:

class AnyClass {
    [string]$Name
    [string]$Id
    [string]$Path
    [psobject]$Value
    [ordered]$PropertyList  # THIS REALLY DID NOT WORK!, but seemed cool. 
    [string]$Parent
}
try {
    $obj = New-Object -TypeName AnyClass
    $obj
}
catch {
    $err = $_
}

This worked with the intended effect:

class AnyClass {
    [string]$Name
    [string]$Id
    [string]$Path
    [psobject]$Value
#  [ordered]$PropertyList         
    [hashtable]$PropertyList = [ordered]@{}     # This worked as intended DOH!
    [string]$Parent
}
try {
    $obj = New-Object -TypeName AnyClass
    $obj
}
catch {
    $err = $_
}