PowerShell / PowerShell/PowerShell

PSPropertyAdapter prevents access to class methods and throws InvalidOperationException

Open
#25,285 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Needs-Triage WG-Engine
Dominant language
C#
Stars
55.5k
Forks
8.5k
Avg merge
1d 2h
Merged PRs (30d)
88

Description

Prerequisites
Steps to reproduce

I have created a PSPropertyAdapter in C# using the PowerShellStandard.Library nuget package to define how PowerShell should interact with my class but doing so seems to have prevented access to any inbuilt and custom methods on my class.

GitHub Repository for sample files
Bluecakes\PowerShellTypeAdapter

Attached Testing Build
PowerShellTypeAdapter.zip

PowerShell 5 Get-Host:

Name             : ConsoleHost
Version          : 5.1.19041.5369
InstanceId       : a8f481db-a9d0-4935-9860-b105005849ba
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-AU
CurrentUICulture : en-GB
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

PowerShell Core Get-Host:

Name             : ConsoleHost
Version          : 7.5.0
InstanceId       : f89f6391-bb7a-43b7-baae-bbe634501e76
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-AU
CurrentUICulture : en-GB
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

I am able to reproduce the issue by added a simple PSPropertyAdapter to the sample cmdlet created with the template dotnet new psmodule.

For testing, i have launched both PowerShell 5 and PowerShell Core with no profile and loaded the module using ipmo ./PowerShellTypeAdapter.dll

Expected behavior

PowerShell should be able to execute a method on a class (such as .ToString())

PowerShell 5:

Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\scripts\psadapter> ipmo .\PowerShellTypeAdapter.psd1
PS C:\scripts\psadapter> $f = New-Favorite -FavoriteNumber 3 -FavoritePet Cat
PS C:\scripts\psadapter> $f.ToString()
PowerShellTypeAdapter.Favorite
PS C:\scripts\psadapter>

PowerShell Core:

PowerShell 7.5.0
PS C:\Program Files\PowerShell\7> cd C:\scripts\psadapter\
PS C:\scripts\psadapter> ipmo .\PowerShellTypeAdapter.psd1
PS C:\scripts\psadapter> $f = New-Favorite -FavoriteNumber 3 -FavoritePet Cat
PS C:\scripts\psadapter> $f.ToString()
PowerShellTypeAdapter.Favorite
PS C:\scripts\psadapter>
Actual behavior

PowerShell 5 works as expected:

Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\scripts\psadapter> ipmo .\PowerShellTypeAdapter.psd1
PS C:\scripts\psadapter> $f = New-Favorite -FavoriteNumber 3 -FavoritePet Cat
PS C:\scripts\psadapter> $f.ToString()
PowerShellTypeAdapter.Favorite
PS C:\scripts\psadapter>

PowerShell Core does not work as expected*
*Method invocation works again after the module is removed (which removes the PSPropertyAdapter typedata):

PowerShell 7.5.0
PS C:\Program Files\PowerShell\7> cd C:\scripts\psadapter\
PS C:\scripts\psadapter> ipmo .\PowerShellTypeAdapter.psd1
PS C:\scripts\psadapter> $f = New-Favorite -FavoriteNumber 3 -FavoritePet Cat
PS C:\scripts\psadapter> $f.ToString()
InvalidOperation: Method invocation failed because [PowerShellTypeAdapter.Favorite] does not contain a method named 'ToString'.
PS C:\scripts\psadapter> Remove-Module PowerShellTypeAdapter
PS C:\scripts\psadapter> $f.ToString()
PowerShellTypeAdapter.Favorite
PS C:\scripts\psadapter>
Error details
PS C:\scripts\psadapter> $e = Get-Error
PS C:\scripts\psadapter> $e

Exception             :
    Type        : System.Management.Automation.RuntimeException
    ErrorRecord :
        Exception             :
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : Method invocation failed because [PowerShellTypeAdapter.Favorite] does not contain a method
named 'ToString'.
            HResult : -2146233087
        CategoryInfo          : InvalidOperation: (:) [], ParentContainsErrorRecordException
        FullyQualifiedErrorId : MethodNotFound
        InvocationInfo        :
            ScriptLineNumber : 1
            OffsetInLine     : 1
            HistoryId        : 5
            Line             : $f.ToString()
            Statement        : $f.ToString()
            PositionMessage  : At line:1 char:1
                               + $f.ToString()
                               + ~~~~~~~~~~~~~
            CommandOrigin    : Internal
        ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
    TargetSite  : System.Object CallSite.Target(System.Runtime.CompilerServices.Closure,
System.Runtime.CompilerServices.CallSite, System.Object)
    Message     : Method invocation failed because [PowerShellTypeAdapter.Favorite] does not contain a method named
'ToString'.
    Data        : System.Collections.ListDictionaryInternal
    Source      : Anonymously Hosted DynamicMethods Assembly
    HResult     : -2146233087
    StackTrace  :
   at CallSite.Target(Closure, CallSite, Object)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at System.Management.Automation.Interpreter.DynamicInstruction`2.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
CategoryInfo          : InvalidOperation: (:) [], RuntimeException
FullyQualifiedErrorId : MethodNotFound
InvocationInfo        :
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : 5
    Line             : $f.ToString()
    Statement        : $f.ToString()
PositionMessage  : At line:1 char:1
                   + $f.ToString()
                   + ~~~~~~~~~~~~~
CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
Environment data

PowerShell 5:

PS C:\scripts\psadapter> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.5369
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.5369
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

PowerShell Core:

PS C:\scripts\psadapter> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.5.0
PSEdition                      Core
GitCommitId                    7.5.0
OS                             Microsoft Windows 10.0.19045
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Visuals

Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked Bluecakes\PowerShellTypeAdapter sample and reproduce the difference between PowerShell 5 and PowerShell 7.5 using the PSPropertyAdapter, module import, and $f.ToString() entry point. Trace how the adapter's typedata affects method lookup; done means class methods remain invocable in PowerShell Core without removing the module.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, powershell
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.