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

AssemblyName.FullName doesn't show PublicKeyToken portion when the AssemblyName instance is returned from AssemblyName.GetAssemblyName #66785

Closed
daxian-dbw opened this issue Mar 17, 2022 · 5 comments · Fixed by #69169
Assignees
Milestone

Comments

@daxian-dbw
Copy link
Contributor

daxian-dbw commented Mar 17, 2022

Description

For an assembly that is not strong-named, AssemblyName.FullName doesn't show PublicKeyToken=null portion when the AssemblyName instance is returned from AssemblyName.GetAssemblyName. This is a regression from .NET 6.

This regression caused one of PowerShell test to fail, which was disabled for the time being:
https://github.com/PowerShell/PowerShell/blob/master/test/xUnit/csharp/test_NativeInterop.cs#L20

However, after the assembly is loaded, the AssemblyName instance returned from Assembly.GetName() works as expected (and as before).

Reproduction Steps

  1. Create a non-strong-named assembly, here is the code for doing that:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Runtime.Loader;
    using System.Management.Automation;
    
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.Emit;
    using Microsoft.CodeAnalysis.Text;
    
    namespace MyApp // Note: actual namespace depends on the project name.
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                string tempDir = Path.Combine(Path.GetTempPath(), "TestLoadNativeInMemoryAssembly");
                string testDll = Path.Combine(tempDir, "test.dll");
    
                if (!File.Exists(testDll))
                {
                    Directory.CreateDirectory(tempDir);
                    bool result = CreateTestDll(testDll);
                }
    
                var asmName = AssemblyName.GetAssemblyName(testDll);
    
                Console.WriteLine($"Assembly: {testDll}");
                Console.WriteLine($"Assembly FullName: {asmName.FullName}");
            }
    
            private static bool CreateTestDll(string dllPath)
            {
                var parseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest);
                var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
    
                List<SyntaxTree> syntaxTrees = new();
                SourceText sourceText = SourceText.From("public class Utt { }");
                syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText, parseOptions));
    
                var refs = new List<PortableExecutableReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) };
                Compilation compilation = CSharpCompilation.Create(
                            Path.GetRandomFileName(),
                            syntaxTrees: syntaxTrees,
                            references: refs,
                            options: compilationOptions);
    
                using var fs = new FileStream(dllPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);
                EmitResult emitResult = compilation.Emit(peStream: fs, options: null);
                return emitResult.Success;
            }
        }
    }
  2. Running the above code with .NET 7-preview.2, you will see the , PublicKeyToken=null part is missing from the Assembly FullName.

Expected behavior

The , PublicKeyToken=null is present, like in .NET 6 and prior .NET versions.

Actual behavior

The , PublicKeyToken=null portion is missing.

Here is what you will see in PowerShell that built with .NET 7-preview.2:

PS:20> [System.Reflection.AssemblyName]::GetAssemblyName("C:\arena\tmp\abc.dll").FullName
qkoexti2.h5p, Version=0.0.0.0, Culture=neutral
PS:15> $t = Add-Type -Path C:\arena\tmp\abc.dll -PassThru
PS:16> $t.Assembly.FullName
qkoexti2.h5p, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
PS:17> $n = $t.Assembly.GetName()
PS:18> $n.FullName
qkoexti2.h5p, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Here is the .NET version:

PS:23> [System.Environment]::Version

Major  Minor  Build  Revision
-----  -----  -----  --------
7      0      0      -1

Regression?

Yes. It's a regression to .NET 6 and prior versions.

Known Workarounds

No response

Configuration

No response

Other information

No response

@ghost
Copy link

ghost commented Mar 17, 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

For an assembly that is not strong-named, AssemblyName.FullName doesn't show PublicKeyToken=null portion when the AssemblyName instance is returned from AssemblyName.GetAssemblyName. This is a regression from .NET 6.

However, after the assembly is loaded, the AssemblyName instance returned from Assembly.GetName() works as expected (and as before).

Reproduction Steps

  1. Create a non-strong-named assembly, here is the code for doing that:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Runtime.Loader;
    using System.Management.Automation;
    
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.Emit;
    using Microsoft.CodeAnalysis.Text;
    
    namespace MyApp // Note: actual namespace depends on the project name.
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                string tempDir = Path.Combine(Path.GetTempPath(), "TestLoadNativeInMemoryAssembly");
                string testDll = Path.Combine(tempDir, "test.dll");
    
                if (!File.Exists(testDll))
                {
                    Directory.CreateDirectory(tempDir);
                    bool result = CreateTestDll(testDll);
                }
    
                var asmName = AssemblyName.GetAssemblyName(testDll);
    
                Console.WriteLine($"Assembly: {testDll}");
                Console.WriteLine($"Assembly FullName: {asmName.FullName}");
            }
    
            private static bool CreateTestDll(string dllPath)
            {
                var parseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest);
                var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
    
                List<SyntaxTree> syntaxTrees = new();
                SourceText sourceText = SourceText.From("public class Utt { }");
                syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText, parseOptions));
    
                var refs = new List<PortableExecutableReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) };
                Compilation compilation = CSharpCompilation.Create(
                            Path.GetRandomFileName(),
                            syntaxTrees: syntaxTrees,
                            references: refs,
                            options: compilationOptions);
    
                using var fs = new FileStream(dllPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);
                EmitResult emitResult = compilation.Emit(peStream: fs, options: null);
                return emitResult.Success;
            }
        }
    }
  2. Running the above code with .NET 7-preview.2, you will see the , PublicKeyToken=null part is missing from the Assembly FullName.

Expected behavior

The , PublicKeyToken=null is present, like in .NET 6 and prior .NET versions.

Actual behavior

The , PublicKeyToken=null portion is missing.

Here is what you will see in PowerShell that built with .NET 7-preview.2:

PS:20> [System.Reflection.AssemblyName]::GetAssemblyName("C:\arena\tmp\abc.dll").FullName
qkoexti2.h5p, Version=0.0.0.0, Culture=neutral
PS:15> $t = Add-Type -Path C:\arena\tmp\abc.dll -PassThru
PS:16> $t.Assembly.FullName
qkoexti2.h5p, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
PS:17> $n = $t.Assembly.GetName()
PS:18> $n.FullName
qkoexti2.h5p, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Here is the .NET version:

PS:23> [System.Environment]::Version

Major  Minor  Build  Revision
-----  -----  -----  --------
7      0      0      -1

Regression?

Yes. It's a regression to .NET 6 and prior versions.

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: daxian-dbw
Assignees: -
Labels:

area-System.Reflection

Milestone: -

@jkotas
Copy link
Member

jkotas commented Mar 17, 2022

cc @VSadov

@VSadov VSadov self-assigned this Mar 17, 2022
@VSadov
Copy link
Member

VSadov commented Mar 17, 2022

Likely introduced by the switch to managed implementation.

@VSadov
Copy link
Member

VSadov commented May 11, 2022

This is a matter of visualizing missing PublicKeyToken - whether we write out PublicKeyToken=null or not if the key is missing.

It looks like 6.0 prints that and we should too, but I wonder if that is always the case or there are other hints to consider on whether to print this or not.

@VSadov
Copy link
Member

VSadov commented May 11, 2022

Interestingly PublicKeyToken that is null is not visualized at all, but PublicKeyToken that is empty (i.e. Length == 0) is visualized as PublicKeyToken=null

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label May 11, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label May 13, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jun 12, 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.

5 participants