Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assembly.GetType("System.Net.Http.HttpClientHandler", false, true) does not find type but finds it when ignoreCase is set to false #65013

Closed
adityapatwardhan opened this issue Feb 8, 2022 · 17 comments · Fixed by #65157

Comments

@adityapatwardhan
Copy link

Description

When trying to do GetType with ignorecase as true does not find the type but finds it when ignoreCase is set to false.

This only happens in .NET7 preview 1 and does not happen in .NET 6.

PowerShell team is using the type in PowerShellGet and it fails to register the endpoint as the type is not found.

Reproduction Steps

Sample program:

public static void Main(string[] args) {

        //string assemblyName = "System.Net.Http.dll";
        //string typeName = "System.Net.Http.HttpClientHandler";
        string assemblyName = args[0];
        string typeName = args[1];

        var myLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);

        string assemblyPath = Path.Join(myLocation, assemblyName);
        var assembly = System.Reflection.Assembly.LoadFile(assemblyPath);

        var typeWithCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: true);
        if (typeWithCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): {typeWithCaseIgnore.FullName} ");
        }

        var typeWithoutCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: false);
        if (typeWithoutCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: false)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): {typeWithoutCaseIgnore.FullName} ");
        }
    }

Output:

HelloWorld.exe System.Net.Http.dll System.Net.Http.HttpClientHandler
Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.HttpClientHandler

But for some other type it works:

HelloWorld.exe System.Xml.dll System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Xml.XmlTextReader

Expected behavior

System.Net.Http.HttpClientHandler is found

Actual behavior

System.Net.Http.HttpClientHandler is NOT found

Regression?

Yes. Works with .NET 6 and below

Known Workarounds

Use ignoreCase as false, but might cause side effects

Configuration

.NET SDK (reflecting any global.json):
Version: 7.0.100-preview.1.22107.7
Commit: fa575c5753

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: <>\AppData\Local\Microsoft\dotnet\sdk\7.0.100-preview.1.22107.7\

Host (useful for support):
Version: 7.0.0-preview.1.22076.8
Commit: 4053379

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Feb 8, 2022
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@adityapatwardhan adityapatwardhan changed the title Assembly.GetType("System.Net.Http.HttpClientHandler", false, true) does not find type with finds it when ignoreCase is set to false Assembly.GetType("System.Net.Http.HttpClientHandler", false, true) does not find type but finds it when ignoreCase is set to false Feb 8, 2022
@ghost
Copy link

ghost commented Feb 8, 2022

Tagging subscribers to this area: @dotnet/area-system-reflection
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

When trying to do GetType with ignorecase as true does not find the type but finds it when ignoreCase is set to false.

This only happens in .NET7 preview 1 and does not happen in .NET 6.

PowerShell team is using the type in PowerShellGet and it fails to register the endpoint as the type is not found.

Reproduction Steps

Sample program:

public static void Main(string[] args) {

        //string assemblyName = "System.Net.Http.dll";
        //string typeName = "System.Net.Http.HttpClientHandler";
        string assemblyName = args[0];
        string typeName = args[1];

        var myLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);

        string assemblyPath = Path.Join(myLocation, assemblyName);
        var assembly = System.Reflection.Assembly.LoadFile(assemblyPath);

        var typeWithCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: true);
        if (typeWithCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): {typeWithCaseIgnore.FullName} ");
        }

        var typeWithoutCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: false);
        if (typeWithoutCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: false)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): {typeWithoutCaseIgnore.FullName} ");
        }
    }

Output:

HelloWorld.exe System.Net.Http.dll System.Net.Http.HttpClientHandler
Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.HttpClientHandler

But for some other type it works:

HelloWorld.exe System.Xml.dll System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Xml.XmlTextReader

Expected behavior

System.Net.Http.HttpClientHandler is found

Actual behavior

System.Net.Http.HttpClientHandler is NOT found

Regression?

Yes. Works with .NET 6 and below

Known Workarounds

Use ignoreCase as false, but might cause side effects

Configuration

.NET SDK (reflecting any global.json):
Version: 7.0.100-preview.1.22107.7
Commit: fa575c5753

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: <>\AppData\Local\Microsoft\dotnet\sdk\7.0.100-preview.1.22107.7\

Host (useful for support):
Version: 7.0.0-preview.1.22076.8
Commit: 4053379

Other information

No response

Author: adityapatwardhan
Assignees: -
Labels:

area-System.Reflection, untriaged

Milestone: -

@mmitche
Copy link
Member

mmitche commented Feb 9, 2022

I believe this is blocking powershell's release for p1.

@adityapatwardhan
Copy link
Author

In addition to the issue in registering endpoints for gallery, PowerShell uses reflection to look up types using Assembly.GetType(, throwonError: false, ignoreCase: true).
The side effect of the issue is that a customer cannot do [System.Net.Http.HttpClientHandler]::new() or New-Object ystem.Net.Http.HttpClientHandler.

@adityapatwardhan
Copy link
Author

/cc @SteveL-MSFT as FYI

@buyaa-n
Copy link
Contributor

buyaa-n commented Feb 9, 2022

Reflection libraries team did not touch the assembly.GetType() code in preview 1, doesn't seem anything change by runtime team that coud affect assembly.GetType() either, anyway it doesn't seem like runtime/reflection issue.

I tried the sample code with 6.0 sdk:

  • With 6.0 System.Net.Http.dll - type found for both (no matter ignorCase is true or flase)
  • With 7.0 System.Net.Http.dll - type not found for both (no matter ignoreCase is true or false)

tried the same code with 7.0 sdk:

  • With 6.0 System.Net.Http.dll - type found for both (no matter ignorCase is true or flase)
  • With 7.0 System.Net.Http.dll - type found for both (no matter ignoreCase is true or false)

Seems something changed in System.Net.Http library in 7.0 or it is just not backward compatable, hopefully the solution is as simple as cleaning/restoring your repo. If that not help @safern @joperezr might help further

@buyaa-n buyaa-n added area-Infrastructure-libraries and removed untriaged New issue has not been triaged by the area owner labels Feb 9, 2022
@ghost
Copy link

ghost commented Feb 9, 2022

Tagging subscribers to this area: @dotnet/area-infrastructure-libraries
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

When trying to do GetType with ignorecase as true does not find the type but finds it when ignoreCase is set to false.

This only happens in .NET7 preview 1 and does not happen in .NET 6.

PowerShell team is using the type in PowerShellGet and it fails to register the endpoint as the type is not found.

Reproduction Steps

Sample program:

public static void Main(string[] args) {

        //string assemblyName = "System.Net.Http.dll";
        //string typeName = "System.Net.Http.HttpClientHandler";
        string assemblyName = args[0];
        string typeName = args[1];

        var myLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);

        string assemblyPath = Path.Join(myLocation, assemblyName);
        var assembly = System.Reflection.Assembly.LoadFile(assemblyPath);

        var typeWithCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: true);
        if (typeWithCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): {typeWithCaseIgnore.FullName} ");
        }

        var typeWithoutCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: false);
        if (typeWithoutCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: false)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): {typeWithoutCaseIgnore.FullName} ");
        }
    }

Output:

HelloWorld.exe System.Net.Http.dll System.Net.Http.HttpClientHandler
Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.HttpClientHandler

But for some other type it works:

HelloWorld.exe System.Xml.dll System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Xml.XmlTextReader

Expected behavior

System.Net.Http.HttpClientHandler is found

Actual behavior

System.Net.Http.HttpClientHandler is NOT found

Regression?

Yes. Works with .NET 6 and below

Known Workarounds

Use ignoreCase as false, but might cause side effects

Configuration

.NET SDK (reflecting any global.json):
Version: 7.0.100-preview.1.22107.7
Commit: fa575c5753

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: <>\AppData\Local\Microsoft\dotnet\sdk\7.0.100-preview.1.22107.7\

Host (useful for support):
Version: 7.0.0-preview.1.22076.8
Commit: 4053379

Other information

No response

Author: adityapatwardhan
Assignees: -
Labels:

area-Infrastructure-libraries, area-System.Reflection

Milestone: -

@adityapatwardhan
Copy link
Author

PowerShell is a standalone app and I believe System.Net.Http.dll comes with the SDK. So, if we build against .NET 7 SDK, we don't really have a choice but to get the .NET 7 version of the assembly.

@safern
Copy link
Member

safern commented Feb 9, 2022

I don't think this is infrastructure related. I just doubled checked the System.Net.Http assembly and compared the .NET 7 P1 vs the .NET 6 one and their metadata is identical (except for assembly versions).

As a note, I tried this on Windows 11 and macOS and it reproed on both OSs. Something interesting that I found that also tells me it has nothing to do with the assembly, is that if I change the type to search for to be System.Net.Http.ByteArrayContent for example, it doesn't fail:

dotnet run
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Net.Http.ByteArrayContent
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.ByteArrayContent
dotnet run
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Net.Http.HttpClient
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.HttpClient
 dotnet run
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Net.Http.HttpContent
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.HttpContent

So it seems like maybe something changed in our string comparisons and it is hitting a bug where ignore case for the specific HttpClientHandler string is not being compared correctly with ignore case.

Adding @tarekgh as he might have some ideas. Also adding @ericstj as this is blocking the p1 release.

@tarekgh
Copy link
Member

tarekgh commented Feb 10, 2022

We need someone from the runtime side to take a look. type system is what handle that

retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, pAssembly->GetAssembly(), (OBJECTREF*)keepAlive.m_ppObject, pBinder);

CC @davidwrighton @jkotas

@buyaa-n
Copy link
Contributor

buyaa-n commented Feb 10, 2022

CC @VSadov

@VSadov VSadov self-assigned this Feb 10, 2022
@VSadov
Copy link
Member

VSadov commented Feb 10, 2022

This could be caused by some of the loader cleanup changes.
I will take a look.

@ghost
Copy link

ghost commented Feb 10, 2022

Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

When trying to do GetType with ignorecase as true does not find the type but finds it when ignoreCase is set to false.

This only happens in .NET7 preview 1 and does not happen in .NET 6.

PowerShell team is using the type in PowerShellGet and it fails to register the endpoint as the type is not found.

Reproduction Steps

Sample program:

public static void Main(string[] args) {

        //string assemblyName = "System.Net.Http.dll";
        //string typeName = "System.Net.Http.HttpClientHandler";
        string assemblyName = args[0];
        string typeName = args[1];

        var myLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);

        string assemblyPath = Path.Join(myLocation, assemblyName);
        var assembly = System.Reflection.Assembly.LoadFile(assemblyPath);

        var typeWithCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: true);
        if (typeWithCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): {typeWithCaseIgnore.FullName} ");
        }

        var typeWithoutCaseIgnore = assembly.GetType(typeName, throwOnError: false, ignoreCase: false);
        if (typeWithoutCaseIgnore is null) {
            Console.WriteLine("Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: false)");
        }
        else {
            Console.WriteLine($"Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): {typeWithoutCaseIgnore.FullName} ");
        }
    }

Output:

HelloWorld.exe System.Net.Http.dll System.Net.Http.HttpClientHandler
Type NOT found with: assembly.GetType(typeName, throwOnError: false, ignoreCase: true)
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Net.Http.HttpClientHandler

But for some other type it works:

HelloWorld.exe System.Xml.dll System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: true): System.Xml.XmlTextReader
Type found with assembly.GetType(typeName, throwOnError: false, ignoreCase: false): System.Xml.XmlTextReader

Expected behavior

System.Net.Http.HttpClientHandler is found

Actual behavior

System.Net.Http.HttpClientHandler is NOT found

Regression?

Yes. Works with .NET 6 and below

Known Workarounds

Use ignoreCase as false, but might cause side effects

Configuration

.NET SDK (reflecting any global.json):
Version: 7.0.100-preview.1.22107.7
Commit: fa575c5753

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: <>\AppData\Local\Microsoft\dotnet\sdk\7.0.100-preview.1.22107.7\

Host (useful for support):
Version: 7.0.0-preview.1.22076.8
Commit: 4053379

Other information

No response

Author: adityapatwardhan
Assignees: VSadov
Labels:

area-Infrastructure-libraries, area-AssemblyLoader-coreclr

Milestone: -

@agocke
Copy link
Member

agocke commented Feb 10, 2022

@safern I can't repro this at all, instead I get: Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'C:\Users\andy\tmp\asmload\bin\Debug\net6.0\System.Net.Http.dll'. The system cannot find the file specified.

Which is what I expect, because System.Net.Http.dll doesn't live next to the user assembly, which should be the entry assembly in the sample case. Did you modify the sample at all?

jkotas added a commit to jkotas/runtime that referenced this issue Feb 10, 2022
The enumerator was missing the last 2 buckets

Fixes dotnet#65013
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Feb 10, 2022
@safern
Copy link
Member

safern commented Feb 10, 2022

Yes I did modify the repro. I changed the GetDirectoryName call to instead of using the executing assembly base directory to use: typeof(string).Assembly.Location

@ericstj
Copy link
Member

ericstj commented Feb 10, 2022

Here's a simplified repro that throws:

var assembly = typeof(HttpClient).Assembly;
var typeName = "System.Net.Http.HttpClientHandler";
Console.WriteLine($"Type: {assembly.GetType(typeName, throwOnError: true, ignoreCase: false)}");
Console.WriteLine($"Type ignoreCase: {assembly.GetType(typeName, throwOnError: true, ignoreCase: true)}");

@agocke
Copy link
Member

agocke commented Feb 10, 2022

It looks like we've found the problem, and Jan has a fix at #65157

jkotas added a commit that referenced this issue Feb 11, 2022
The enumerator was missing the last 2 buckets

Fixes #65013
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 11, 2022
jkotas added a commit to jkotas/runtime that referenced this issue Feb 11, 2022
The enumerator was missing the last 2 buckets

Fixes dotnet#65013
@ghost ghost added in-pr There is an active PR which will close this issue when it is merged and removed in-pr There is an active PR which will close this issue when it is merged labels Feb 11, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Mar 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.