PowerShell / vscode-powershell

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

Casting problems in Visual Studio Code Windows Powershell 5.1 terminal #4426

Open SamLowryMOI opened 1 year ago

SamLowryMOI commented 1 year ago

Prerequisites

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

SydneyhSmith commented 1 year ago

Thanks @SamLowryMOI sounds like the workaround is to use PowerShell 7, this looks like an issue with the GAC

SamLowryMOI commented 1 year ago

looks like an issue with the GAC

I don't think so, the GAC is the same for all programmes, isn't it?

I compared which Powershell 5.1 assemblies are loaded in the Windows console and the VS Code Terminal.

These dlls are loaded by both:

GlobalAssemblyCache FullName
------------------- --------
              False Anonymously Hosted DynamicMethods Assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
               True Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True Microsoft.Management.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.Commands.Utility, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.ConsoleHost, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.ConsoleHost.resources, Version=3.0.0.0, Culture=de, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.Security, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True mscorlib.resources, Version=4.0.0.0, Culture=de, PublicKeyToken=b77a5c561934e089
               True System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.DirectoryServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True System.Management.Automation.resources, Version=3.0.0.0, Culture=de, PublicKeyToken=31bf3856ad364e35
               True System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

This dll is only loaded by the Windows console:

GlobalAssemblyCache FullName
------------------- --------
              False Microsoft.Powershell.PSReadline, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

These dlls are only loaded by the VS Code Terminal:

GlobalAssemblyCache FullName
------------------- --------
              False MediatR, Version=8.0.0.0, Culture=neutral, PublicKeyToken=bb9a41a5e8aaa7e2
              False Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
              False Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60      
              False Microsoft.Extensions.DependencyInjection.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
              False Microsoft.Extensions.Logging, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
              False Microsoft.Extensions.Logging.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
              False Microsoft.Extensions.Options, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
              False Microsoft.Extensions.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
              False Microsoft.PowerShell.CrossCompatibility, Version=1.21.0.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.PowerShell.EditorServices, Version=3.8.1.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.PowerShell.EditorServices.Hosting, Version=3.8.1.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.PowerShell.EditorServices.VSCode, Version=3.8.1.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.PowerShell.PSReadLine.Polyfiller, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.PowerShell.PSReadLine2, Version=2.2.6.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.VisualStudio.Threading, Version=16.10.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              False Microsoft.VisualStudio.Validation, Version=16.10.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              False Microsoft.Windows.PowerShell.ScriptAnalyzer, Version=1.21.0.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules, Version=1.21.0.0, Culture=neutral, PublicKeyToken=null        
              False Nerdbank.Streams, Version=2.8.0.0, Culture=neutral, PublicKeyToken=cac503e1823ce71c
              False Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
              False Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
              False OmniSharp.Extensions.DebugAdapter, Version=0.19.0.0, Culture=neutral, PublicKeyToken=6d868dff454e6022
              False OmniSharp.Extensions.DebugAdapter.Server, Version=0.19.0.0, Culture=neutral, PublicKeyToken=6d868dff454e6022
              False OmniSharp.Extensions.JsonRpc, Version=0.19.0.0, Culture=neutral, PublicKeyToken=6d868dff454e6022
              False OmniSharp.Extensions.LanguageProtocol, Version=0.19.0.0, Culture=neutral, PublicKeyToken=6d868dff454e6022
              False OmniSharp.Extensions.LanguageServer, Version=0.19.0.0, Culture=neutral, PublicKeyToken=6d868dff454e6022
              False OmniSharp.Extensions.LanguageServer.Shared, Version=0.19.0.0, Culture=neutral, PublicKeyToken=6d868dff454e6022
              False Serilog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10
              False Serilog.Extensions.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10
              False Serilog.Sinks.Async, Version=1.5.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10
              False Serilog.Sinks.File, Version=5.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10
              False System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
              False System.Collections.Immutable, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              False System.IO.Pipelines, Version=5.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
              False System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
              False System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              False System.Reactive, Version=5.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263
              False System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              False System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
              False System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
               True Microsoft.PowerShell.Commands.Diagnostics, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.Commands.Management, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.Commands.Utility.resources, Version=3.0.0.0, Culture=de, PublicKeyToken=31bf3856ad364e35
               True Microsoft.PowerShell.Security.resources, Version=3.0.0.0, Culture=de, PublicKeyToken=31bf3856ad364e35
               True Microsoft.WSMan.Management, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
               True Microsoft.WSMan.Management.resources, Version=3.0.0.0, Culture=de, PublicKeyToken=31bf3856ad364e35
               True netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
               True System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.Dynamic, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Reflection.Emit.ILGeneration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Reflection.Emit.Lightweight, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.resources, Version=4.0.0.0, Culture=de, PublicKeyToken=b77a5c561934e089
               True System.Runtime.InteropServices.RuntimeInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
               True System.ValueTuple, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
               True System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
               True System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

You can see that the VS Code Terminal loads 57 dlls in addition.

I don't know the tasks of the additional dlls, but labels like

              False Microsoft.VisualStudio.Validation, Version=16.10.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              False Microsoft.Windows.PowerShell.ScriptAnalyzer, Version=1.21.0.0, Culture=neutral, PublicKeyToken=null
              False Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules, Version=1.21.0.0, Culture=neutral, PublicKeyToken=null        

lead me to believe that the VS Code Terminal performs additional checks and, in contrast to the Windows console, makes a distinction between classes and interfaces.

But unfortunately, there is no way around this, as Powershell does not make a difference despite the correct declaration.

And as workarounds, I run the script in VS Code with the extension "Run in Powershell" and debug in Powershell ISE.

andyleejordan commented 1 year ago

What Sydney means is that, since Windows PowerShell 5.1 uses the .NET Framework, it has to use the GAC for assembly resolution instead of an Assembly Load Context (as available in PowerShell Core 7.x because it's built on .NET Core). This means that when using 5.1, the dependencies of the extension (the module PowerShell Editor Services and its dependencies, as you listed out) are not able to be isolated, thus leading to this problem where it works in a non-Extension Terminal, and it works in an Extension Terminal when using 7.x.

SamLowryMOI commented 1 year ago

@andschwa This explains why the terminal loads the additional dlls, but not why the error occurs.

Loading a dll and using it are different things, aren't they?

If it is necessary to use a specific debugger that recognises the difference between OptionsMonitor and IOptionsMonitor because of the limitations you mentioned, ok.

But the error still occurs primarily because of the debugger. Or not?

I would just like to understand it.