Casting problems in Visual Studio Code Windows Powershell 5.1 terminal

Ouverte
#4,426 4 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
28/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
À l'abandon
Stack technique
powershell, typescript, vscode

Piste de recherche

Commencez par exécuter le script de reproduction inline avec les DLL Microsoft.Extensions v7.0.0 référencées dans le terminal Windows PowerShell 5.1, puis comparez-le aux consoles fonctionnelles répertoriées. Inspectez la configuration du terminal et de la session PowerShell de l’extension afin d’identifier pourquoi les mêmes types génériques sont chargés de manière incompatible. La tâche est terminée lorsque le comportement propre à VS Code est expliqué et qu’un chemin reproductible pour les constructeurs et les casts signalés est documenté ou corrigé.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Bug: PowerShell 5.1 Issue-Bug
Prerequisites
  • I have written a descriptive issue title.
  • I have searched all open and closed issues to ensure it has not already been reported.
  • I have read the troubleshooting guide.
  • I am sure this issue is with the extension itself and does not reproduce in a standalone PowerShell instance.
  • I have verified that I am using the latest version of Visual Studio Code and the PowerShell extension.
  • If this is a security issue, I have read the security issue reporting guidance.
Summary

I have had these casting problems several times. Now I am taking the time to document them. They were always error messages like "Type A cannot be converted to type A". But only in the Windows Powershell 5.1 terminal.

Also, the example script below in "Steps to Reproduce" does not work in the Windows Powershell 5.1 terminal only.

Expected:

info: int[0]
      Hello from Windows Powershell

But I get this:

PS C:\GithubIssue> . 'C:\GithubIssue\Github VS Code.ps1'
Cannot find an overload for "new" and the argument count: "1".
At C:\GithubIssue\Github VS Code.ps1:26 char:1
+ $loggerFactory = [Microsoft.Extensions.Logging.LoggerFactory]::new(
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException  
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest
 
Cannot find an overload for "new" and the argument count: "1".
At C:\GithubIssue\Github VS Code.ps1:61 char:5
+     [Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider]::new ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    + CategoryInfo          : NotSpecified: (:) [], MethodException        
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest
 
Constructor not found.
Constructor not found.
Microsoft.Extensions.Options.IOptionsMonitor`1[[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions, Microsoft.Extensions.Logging.Console, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]
Microsoft.Extensions.Options.OptionsMonitor`1[[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions, Microsoft.Extensions.Logging.Console, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]
Exception calling "Invoke" with "1" argument(s): "Object of type 
'Microsoft.Extensions.Options.OptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]' cannot be converted to type 
'Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]'."
At C:\GithubIssue\Github VS Code.ps1:86 char:5
+     $foolMe = $constructor.Invoke(@($optionsMonitor))
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException
 
Exception calling "Invoke" with "1" argument(s): "Object of type 
'Microsoft.Extensions.Options.OptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]' cannot be converted to type 
'Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]'."
At C:\GithubIssue\Github VS Code.ps1:90 char:5
+     $foolMe = $constructor.Invoke(@($cast))
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException
 
Exception calling "Invoke" with "1" argument(s): "Object of type 
'Microsoft.Extensions.Options.OptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]' cannot be converted to type 
'Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]'."
At C:\GithubIssue\Github VS Code.ps1:94 char:5
+     $foolMe = $constructor.Invoke(@($cast))
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException

The crucial error is:

 "Object of type 
'Microsoft.Extensions.Options.OptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]' cannot be converted to type 
'Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]'."

Why does this happen and how can I avoid it?

I know that one type is an interface. But for one thing, Powershell doesn't know the difference. On the other hand, why does it work in a Windows Powershell 5.1 console, but not in the Windows Powershell 5.1 terminal of VS Code?

PowerShell Version
PS C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.2364
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.2364
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
Visual Studio Code Version
PS C:\> code --version
1.75.1
441438abd1ac652551dbe4d408dfcec8a499b8bf
x64
Extension Version
PS C:\> code --list-extensions --show-versions | Select-String powershell

ms-vscode.powershell@2023.1.0
tobysmith568.run-in-powershell@1.1.1
Steps to Reproduce
# This works fine in
# Windows Powershell 5.1 console
# Powershell Core 7.3.2 console
# Visual Studio Code Powershell Core 7.3.2 terminal
# BUT NOT IN
# Visual Studio Code Windows Powershell 5.1 terminal

Add-Type -Path "$PSScriptRoot\v7.0.0\Microsoft.Extensions.Logging.dll"
Add-Type -Path "$PSScriptRoot\v7.0.0\Microsoft.Extensions.Logging.Console.dll"
Add-Type -Path "$PSScriptRoot\v7.0.0\Microsoft.Extensions.Options.dll"


$configureNamedOptions = [Microsoft.Extensions.Options.ConfigureNamedOptions[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]]::new('', $null)

$optionsFactory = [Microsoft.Extensions.Options.OptionsFactory[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]]::new(
    [Microsoft.Extensions.Options.ConfigureNamedOptions[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions][]] @($configureNamedOptions), 
    [System.Collections.Generic.List[Microsoft.Extensions.Options.IPostConfigureOptions[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]]]::new()
)

$optionsMonitor = [Microsoft.Extensions.Options.OptionsMonitor[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]]::new(
    $optionsFactory,
    [System.Collections.Generic.List[Microsoft.Extensions.Options.IOptionsChangeTokenSource[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]]]::new(),
    [Microsoft.Extensions.Options.OptionsCache[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]]::new()
)

$loggerFactory = [Microsoft.Extensions.Logging.LoggerFactory]::new(
    [Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider[]] @([Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider]::new($optionsMonitor)),
    [Microsoft.Extensions.Logging.LoggerFilterOptions] @{ MinLevel = [Microsoft.Extensions.Logging.LogLevel]::Trace }
)

if ($null -ne $loggerFactory) {
    $method = [Microsoft.Extensions.Logging.LoggerFactoryExtensions].GetMethod('CreateLogger',
        [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::Public, $null, 
        [Type[]]@([Microsoft.Extensions.Logging.ILoggerFactory]), $null
    )

    $method = $method.MakeGenericMethod(@([int]))
    $logger = $method.Invoke($null, @($loggerFactory))

    $method = [Microsoft.Extensions.Logging.LoggerExtensions].GetMethod('LogInformation',
        [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::Public, 
        $null, 
        [Type[]]@([Microsoft.Extensions.Logging.ILogger], [string], [object[]]), 
        $null
    )

    $loggerFactory.Dispose()
}

if ($null -ne $logger) {
    if ($PSVersionTable.PSVersion.Major -gt 5) {
        $method.Invoke($null, @($logger, "Hello from Powershell Core", $null))
    }
    else {
        $method.Invoke($null, @($logger, "Hello from Windows Powershell", $null))
    }
}

### Try to narrow down the error ####################################################################
if ($null -eq $loggerFactory) {
    # Get original error message.
    [Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider]::new($optionsMonitor)
    # Get a better error message.

    $constructor = [Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider].GetConstructor( 
        [Type[]]@([Microsoft.Extensions.Options.OptionsMonitor[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions]], [string], [object[]])
    )

    if ($null -eq $constructor) {
        Write-Host -F Yellow 'Constructor not found.'
    }
    # Let's try FullName.
    $constructor = [Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider].GetConstructor( 
        [Type[]]@([Microsoft.Extensions.Options.IOptionsMonitor[[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions, Microsoft.Extensions.Logging.Console, Version = 7.0.0.0, Culture = neutral, PublicKeyToken = adb9793829ddae60]]], [string], [object[]])
    )

    if ($null -eq $constructor) {
        Write-Host -F Yellow 'Constructor not found.'
    }

    #But it exists!
    $constructor = [Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider].GetConstructors()[0]
    $constructor.GetParameters().ParameterType.FullName
    $optionsMonitor.GetType().FullName

    # Try constructor.
    $foolMe = $constructor.Invoke(@($optionsMonitor))

    # Ok, try to cast it.
    $cast = [Microsoft.Extensions.Options.IOptionsMonitor[[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions, Microsoft.Extensions.Logging.Console, Version = 7.0.0.0, Culture = neutral, PublicKeyToken = adb9793829ddae60]]] $optionsMonitor
    $foolMe = $constructor.Invoke(@($cast))

    # Ok, try to cast it again.
    $cast = $optionsMonitor -as [Microsoft.Extensions.Options.IOptionsMonitor[[Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions, Microsoft.Extensions.Logging.Console, Version = 7.0.0.0, Culture = neutral, PublicKeyToken = adb9793829ddae60]]]
    $foolMe = $constructor.Invoke(@($cast))

    # I give up.
}
Visuals

No response

Logs

No response

Langage dominant
TypeScript
Étoiles
1.9k
Forks
548
Métriques de merge des PR
Aucune PR mergée en 30 j

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de PowerShell/vscode-powershell

Toutes les issues de PowerShell/vscode-powershell

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.