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

DispatchProxy.Create reads AssemblyLoadContext.Name but treats it as an assembly name #80387

Closed
philiphendry opened this issue Jan 4, 2023 · 17 comments

Comments

@philiphendry
Copy link

Describe the bug

An msbuild task that calls a WCF service errors when running with dotNet 7.0. This occurred after a Visual Studio upgrade which delivered dotNet 7.0 alongside the already installed dotNet 6.0.

To Reproduce

Here I've attached a minimalist project that reproduces the issue:
DotNet7BuildBug.zip

To see the problem follow these steps:

  1. Ensure dotNet Core SDK 7.0 is installed.
  2. Load the solution into Visual Studio
  3. Run dotnet publish .\BuildTools\ from the root folder.
  4. Run dotnet msbuild .\Test.msbuild. This highlights the issue being raised and raises the exception shown below.

We are currently working around this problem by adding a global.json targeting the core 6.0 runtime and this can be demonstrated in the attached application by renaming the provided global.json.bak file. Before running the msbuild, start the WcfServiceLibrary so the service host is available and this will allow the mean the msbuild will run without error.

Exceptions (if any)

C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018: The "LoadTask" task failed unexpectedly.
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018: System.IO.FileLoadException: The given assembly name was invalid.
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018: File name: 'DispatchProxyTypes.MSBuild plugin C:\temp\DotNet7BuildBug\BuildTools\bin\Debug\net6.0\publish\BuildTools.dll'
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.ThrowInvalidAssemblyName()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.GetNextToken(String& tokenString)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.Parse()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.Parse(String name)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyName..ctor(String assemblyName)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxyGenerator.ProxyAssembly..ctor(AssemblyLoadContext alc)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxyGenerator.<>c.<CreateProxyInstance>b__6_0(AssemblyLoadContext x)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValueLocked(TKey key, CreateValueCallback createValueCallback)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxyGenerator.CreateProxyInstance(Type baseType, Type interfaceType)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxy.Create[T,TProxy]()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.Channels.ServiceChannelProxy.CreateProxy[TChannel](MessageDirection direction,ServiceChannel serviceChannel)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.Channels.ServiceChannelFactory.CreateProxy[TChannel](MessageDirection direction, ServiceChannel serviceChannel)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.Channels.ServiceChannelFactory.CreateChannel[TChannel](EndpointAddress address, Uri via)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ChannelFactory`1.CreateChannel()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ClientBase`1.CreateChannel()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ClientBase`1.CreateChannelInternal()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ClientBase`1.get_Channel()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at ServiceReference1.Service1Client.GetDataAsync(Int32 value) in C:\temp\DotNet7BuildBug\BuildTools\Connected Services\ServiceReference1\Reference.cs:line 116
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at BuildTools.LoadTask.Execute() in C:\temp\DotNet7BuildBug\BuildTools\LoadTask.cs:line 10
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

Further technical details

Output from dotnet --info:

.NET SDK:
 Version:   7.0.101
 Commit:    bb24aafa11

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\7.0.101\

Host:
  Version:      7.0.1
  Architecture: x64
  Commit:       97203d38ba

.NET SDKs installed:
  3.1.426 [C:\Program Files\dotnet\sdk]
  5.0.403 [C:\Program Files\dotnet\sdk]
  5.0.408 [C:\Program Files\dotnet\sdk]
  5.0.410 [C:\Program Files\dotnet\sdk]
  6.0.200 [C:\Program Files\dotnet\sdk]
  6.0.202 [C:\Program Files\dotnet\sdk]
  6.0.203 [C:\Program Files\dotnet\sdk]
  6.0.301 [C:\Program Files\dotnet\sdk]
  6.0.302 [C:\Program Files\dotnet\sdk]
  6.0.307 [C:\Program Files\dotnet\sdk]
  6.0.401 [C:\Program Files\dotnet\sdk]
  6.0.404 [C:\Program Files\dotnet\sdk]
  7.0.101 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.27 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.27 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.27 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

Visual Studio version information:

Microsoft Visual Studio Enterprise 2022
Version 17.4.3
VisualStudio.17.Release/17.4.3+33205.214
Microsoft .NET Framework
Version 4.8.04084

Installed Version: Enterprise

Visual C++ 2022   00476-80000-00000-AA277
Microsoft Visual C++ 2022

ADL Tools Service Provider   1.0
This package contains services used by Data Lake tools

ASA Service Provider   1.0

ASP.NET and Web Tools   17.4.326.54890
ASP.NET and Web Tools

Azure App Service Tools v3.0.0   17.4.326.54890
Azure App Service Tools v3.0.0

Azure Data Lake Tools for Visual Studio   2.6.5000.0
Microsoft Azure Data Lake Tools for Visual Studio

Azure Functions and Web Jobs Tools   17.4.326.54890
Azure Functions and Web Jobs Tools

Azure Stream Analytics Tools for Visual Studio   2.6.5000.0
Microsoft Azure Stream Analytics Tools for Visual Studio

C# Tools   4.4.0-6.22580.4+d7a61210a88b584ca0827585ec6e871c6b1c5a14
C# components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.

Common Azure Tools   1.10
Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.

File Differ   3.0.43
The easiest way to diff two files directly in Solution Explorer

File Icons   2.7
Adds icons for files that are not recognized by Solution Explorer

iMeta CLM Cdmu Editor   1.0
A Cdmu rule editor for iMeta CLM modules.

iMeta CLM Csx Rule Editor   1.0
A Csx rule editor for iMeta CLM modules.

iMeta CLM User Group Config Editor   1.0
Editor for iMeta CLM module User Group Configuration

Microsoft Azure Hive Query Language Service   2.6.5000.0
Language service for Hive query

Microsoft Azure Stream Analytics Language Service   2.6.5000.0
Language service for Azure Stream Analytics

Microsoft Azure Tools for Visual Studio   2.9
Support for Azure Cloud Services projects

Microsoft JVM Debugger   1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines

Node.js Tools   1.5.40817.1 Commit Hash:66443775f9f3b1d8f8fee47af5002828b346688d
Adds support for developing and debugging Node.js apps in Visual Studio

NuGet Package Manager   6.4.0
NuGet Package Manager in Visual Studio. For more information about NuGet, visit https://docs.nuget.org/

Razor (ASP.NET Core)   17.0.0.2246202+61cc048d36a3fc9246d2f04625988b19a18ab8f0
Provides languages services for ASP.NET Core Razor.

RuleVisualiserWindow Extension   1.0
RuleVisualiserWindow Visual Studio Extension Detailed Info

SQL Server Data Tools   17.0.62207.28050
Microsoft SQL Server Data Tools

SVG Viewer   1.0.16
Makes it much easier to work with SVG files by showing a live preview in the bottom-right corner of the code window

ToolWindowHostedEditor   1.0
Hosting json editor into a tool window

TypeScript Tools   17.0.10921.2001
TypeScript Tools for Microsoft Visual Studio

Visual Basic Tools   4.4.0-6.22580.4+d7a61210a88b584ca0827585ec6e871c6b1c5a14
Visual Basic components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.

Visual F# Tools   17.4.0-beta.22512.4+525d5109e389341bb90b144c24e2ad1ceec91e7b
Microsoft Visual F# Tools

Visual Studio Extension for SpecFlow   1.0
Visual Studio extension for working with SpecFlow projects and Gherkin feature files.

Visual Studio IntelliCode   2.2
AI-assisted development for Visual Studio.

VSColorOutput64   2022.2
Color output for build and debug windows - https://mike-ward.net/vscoloroutput
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Jan 4, 2023
@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.

@KalleOlaviNiemitalo
Copy link

I think it's a .NET Runtime bug. DispatchProxyGenerator should not attempt to parse AssemblyLoadContext.Name as AssemblyName. Rather it should copy the string as is to AssemblyName.Name. AssemblyName.FullName is able to quote whatever you put in AssemblyName.Name.

@KalleOlaviNiemitalo
Copy link

Can you work around by setting MSBUILDSINGLELOADCONTEXT=1 in the environment?

@KalleOlaviNiemitalo
Copy link

KalleOlaviNiemitalo commented Jan 4, 2023

MSBuild generates an AssemblyLoadContext.Name that likely includes backslashes that AssemblyNameParser treats as escape characters:

https://github.com/dotnet/msbuild/blob/2badb37d109910fbd3155cf8743224b7a27494d8/src/Shared/MSBuildLoadContext.cs#L35-L36

if (c == '\\')
{
c = GetNextChar();
switch (c)
{
case '\\':
case ',':
case '=':
case '\'':
case '"':
sb.Append(c);
break;
case 't':
sb.Append('\t');
break;
case 'r':
sb.Append('\r');
break;
case 'n':
sb.Append('\n');
break;
default:
ThrowInvalidAssemblyName();
break; //unreachable
}
}

@KalleOlaviNiemitalo
Copy link

This use of AssemblyLoadContext.Name in DispatchProxy came from #62095, which has been locked, so I cannot comment there. It has not been fixed on the main branch of dotnet/runtime yet, and I did not find any dotnet/runtime issue filed for this problem.

@philiphendry
Copy link
Author

@KalleOlaviNiemitalo great analysis, thank you :)

I've tried the MSBUILDSINGLELOADCONTEXT environment variable and that does seem to resolve the issue but what would be the consequence of this and is this a better workaround than using a global.json?

Should I create a new issue in dotnet/runtime and close this one?

@KalleOlaviNiemitalo
Copy link

I expect the team can move this issue to dotnet/runtime.

For solutions that target .NET 6.0, I'd prefer global.json rather than the environment variable. One reason is that .NET SDK 7 will go out of support before .NET SDK 6.

@KalleOlaviNiemitalo
Copy link

Here's a demo that shows the .NET Runtime regression without involving WCF.

Sdk29734.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
    <LangVersion>7.3</LangVersion>
  </PropertyGroup>

</Project>

Program.cs:

using System;
using System.Reflection;
using System.Runtime.Loader;

namespace Sdk29734
{
    public static class Program
    {
        static void Main()
        {
            var alc = new AssemblyLoadContext(name: @"Don't parse C:\");
            Assembly assembly = alc.LoadFromAssemblyPath(typeof(Program).Assembly.Location);
            Type type = assembly.GetType(typeof(Program).FullName);
            MethodInfo method = type.GetMethod("Demo", BindingFlags.Public | BindingFlags.Static);
            method.Invoke(null, null);
        }

        public static void Demo()
        {
            Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(Program).Assembly).Name);
            IDemo proxy = DispatchProxy.Create<IDemo, Proxy>();
            proxy.Method();
        }
    }

    internal interface IDemo
    {
        void Method();
    }

    internal class Proxy : DispatchProxy
    {
        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            Console.WriteLine(targetMethod);
            return null;
        }
    }
}

Runs with .NET 6.0.12:

$ dotnet run --framework=net6.0
Don't parse C:\
Void Method()

Fails with .NET 7.0.1:

$ dotnet run --framework=net7.0
Don't parse C:\
Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.FileLoadException: The given assembly name was invalid.
File name: 'DispatchProxyTypes.Don't parse C:\'
   at System.Reflection.AssemblyNameParser.ThrowInvalidAssemblyName()
   at System.Reflection.AssemblyNameParser.GetNextToken(String& tokenString)
   at System.Reflection.AssemblyNameParser.Parse()
   at System.Reflection.AssemblyNameParser.Parse(String name)
   at System.Reflection.AssemblyName..ctor(String assemblyName)
   at System.Reflection.DispatchProxyGenerator.ProxyAssembly..ctor(AssemblyLoadContext alc)
   at System.Reflection.DispatchProxyGenerator.<>c.<CreateProxyInstance>b__6_0(AssemblyLoadContext x)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValueLocked(TKey key, CreateValueCallback createValueCallback)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
   at System.Reflection.DispatchProxyGenerator.CreateProxyInstance(Type baseType, Type interfaceType)
   at System.Reflection.DispatchProxy.Create[T,TProxy]()
   at Sdk29734.Program.Demo() in [REDACTED]\Program.cs:line 21
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Sdk29734.Program.Main() in [REDACTED]\Program.cs:line 15

@KalleOlaviNiemitalo
Copy link

KalleOlaviNiemitalo commented Jan 4, 2023

Rather it should copy the string as is to AssemblyName.Name. AssemblyName.FullName is able to quote whatever you put in AssemblyName.Name.

Ugh, it isn't that simple. Even though one can set AssemblyName.Name = @"DispatchProxyTypes.MSBuild plugin C:\temp\DotNet7BuildBug\BuildTools\bin\Debug\net6.0\publish\BuildTools.dll", and AssemblyName.FullName nicely doubles the backslashes, AssemblyBuilder.DefineDynamicAssembly then rejects the name.

System.ArgumentException: The given assembly name was invalid.
   at System.Reflection.Emit.AssemblyBuilder.CreateDynamicAssembly(AssemblyLoadContext assemblyLoadContext, AssemblyName name, AssemblyBuilderAccess access)
   at System.Reflection.Emit.AssemblyBuilder..ctor(AssemblyName name, AssemblyBuilderAccess access, Assembly callingAssembly, AssemblyLoadContext assemblyLoadContext, IEnumerable`1 assemblyAttributes)
   at System.Reflection.Emit.AssemblyBuilder.InternalDefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, Assembly callingAssembly, AssemblyLoadContext assemblyLoadContext, IEnumerable`1 assemblyAttributes)
   at System.Reflection.Emit.AssemblyBuilder.DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)

I guess it blows up in unmanaged Assembly::CreateDynamic, which rejects backslashes, colons, and slashes:

if (COMCharacter::nativeIsWhiteSpace(pAssemblyNameParts->_pName[0])
|| wcschr(pAssemblyNameParts->_pName, '\\') != NULL
|| wcschr(pAssemblyNameParts->_pName, ':') != NULL
|| wcschr(pAssemblyNameParts->_pName, '/') != NULL)
{
COMPlusThrow(kArgumentException, W("InvalidAssemblyName"));
}

So, DispatchProxyGenerator needs to be fixed in some other way. The simplest change would be to make DispatchProxyGenerator always use $"DispatchProxyTypes.{alc.GetHashCode()}", as if AssemblyLoadContext.Name were null.

string name;
if (alc == AssemblyLoadContext.Default)
{
name = "ProxyBuilder";
}
else
{
string? alcName = alc.Name;
name = string.IsNullOrEmpty(alcName) ? $"DispatchProxyTypes.{alc.GetHashCode()}" : $"DispatchProxyTypes.{alcName}";
}

For debuggability though, it would be nicer to mangle the name, e.g. replace disallowed characters with underscores.

@KalleOlaviNiemitalo
Copy link

KalleOlaviNiemitalo commented Jan 5, 2023

https://github.com/dotnet/corefx/issues/34791, it was suggested:

  • The Assembly.LoadFile(path) generated ALCs would be constructed with name = "Assembly.LoadFile(path)" .

which is what Assembly.LoadFile does:

AssemblyLoadContext alc = new IndividualAssemblyLoadContext($"Assembly.LoadFile({normalizedPath})");

Therefore, this bug can also be reproduced without explicitly specifying AssemblyLoadContext.Name.

Sdk29734.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
    <LangVersion>7.3</LangVersion>
  </PropertyGroup>

</Project>

Program.cs:

using System;
using System.Reflection;
using System.Runtime.Loader;

namespace Sdk29734
{
    public static class Program
    {
        static void Main()
        {
            Assembly assembly = Assembly.LoadFile(typeof(Program).Assembly.Location);
            Type type = assembly.GetType(typeof(Program).FullName);
            MethodInfo method = type.GetMethod(nameof(Demo), BindingFlags.Public | BindingFlags.Static);
            method.Invoke(null, null);
        }

        public static void Demo()
        {
            Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(Program).Assembly).Name);
            IDemo proxy = DispatchProxy.Create<IDemo, Proxy>();
            proxy.Method();
        }
    }

    internal interface IDemo
    {
        void Method();
    }

    internal class Proxy : DispatchProxy
    {
        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            Console.WriteLine(targetMethod);
            return null;
        }
    }
}

Runs with .NET 6.0.12:

$ dotnet run --framework=net6.0
Assembly.LoadFile(C:\[REDACTED]\Sdk29734\bin\Debug\net6.0\Sdk29734.dll)
Void Method()

Fails with .NET 7.0.1:

$ dotnet run --framework=net7.0
Assembly.LoadFile(C:\[REDACTED]\Sdk29734\bin\Debug\net7.0\Sdk29734.dll)
Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.FileLoadException: The given assembly name was invalid.
File name: 'DispatchProxyTypes.Assembly.LoadFile(C:\[REDACTED]\Sdk29734\bin\Debug\net7.0\Sdk29734.dll)'
   at System.Reflection.AssemblyNameParser.ThrowInvalidAssemblyName()
   at System.Reflection.AssemblyNameParser.GetNextToken(String& tokenString)
   at System.Reflection.AssemblyNameParser.Parse()
   at System.Reflection.AssemblyNameParser.Parse(String name)
   at System.Reflection.AssemblyName..ctor(String assemblyName)
   at System.Reflection.DispatchProxyGenerator.ProxyAssembly..ctor(AssemblyLoadContext alc)
   at System.Reflection.DispatchProxyGenerator.<>c.<CreateProxyInstance>b__6_0(AssemblyLoadContext x)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValueLocked(TKey key, CreateValueCallback createValueCallback)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
   at System.Reflection.DispatchProxyGenerator.CreateProxyInstance(Type baseType, Type interfaceType)
   at System.Reflection.DispatchProxy.Create[T,TProxy]()
   at Sdk29734.Program.Demo() in C:\[REDACTED]\Sdk29734\Program.cs:line 20
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Sdk29734.Program.Main() in C:\[REDACTED]\Sdk29734\Program.cs:line 14

@KalleOlaviNiemitalo
Copy link

KalleOlaviNiemitalo commented Jan 5, 2023

MSBuild could be changed to work around this issue by not naming the assembly load contexts. Such a change could be helpful in case the AssemblyLoadContext fix is considered too risky for .NET 7.

The custom MSBuild task cannot work around this issue by assigning null to AssemblyLoadContext.Name, because it is a read-only property.

The custom MSBuild task could perhaps work around this issue by creating another AssemblyLoadContext without a name, and delegating the virtual methods to the AssemblyLoadContext that MSBuild created. Such a task would not be able to target netstandard2.0, though. Also, it might be difficult to forward the AssemblyLoadContext events to MSBuild's AssemblyLoadContext so that MSBuild can handle them.

@marcpopMSFT marcpopMSFT transferred this issue from dotnet/sdk Jan 9, 2023
@rainersigwald
Copy link
Member

I agree with @KalleOlaviNiemitalo that this sounds like more of a runtime bug than MSBuild.

MSBuild could be changed to work around this issue by not naming the assembly load contexts. Such a change could be helpful in case the AssemblyLoadContext fix is considered too risky for .NET 7.

Agreed, though I would rather not do this as the info we put in the name seems handy. But not that handy, since it's only in the debugger. If we have to I wouldn't object too strongly.

@rainersigwald rainersigwald removed the untriaged New issue has not been triaged by the area owner label Jan 9, 2023
@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.

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jan 9, 2023
@rainersigwald rainersigwald transferred this issue from dotnet/msbuild Jan 9, 2023
@rainersigwald rainersigwald changed the title MSBuild task calling WCF service fails with exception with dotNet 7.0 DispatchProxy.Create reads AssemblyLoadContext.Name but treats it as an assembly name Jan 9, 2023
@ghost
Copy link

ghost commented Jan 10, 2023

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

Issue Details

Describe the bug

An msbuild task that calls a WCF service errors when running with dotNet 7.0. This occurred after a Visual Studio upgrade which delivered dotNet 7.0 alongside the already installed dotNet 6.0.

To Reproduce

Here I've attached a minimalist project that reproduces the issue:
DotNet7BuildBug.zip

To see the problem follow these steps:

  1. Ensure dotNet Core SDK 7.0 is installed.
  2. Load the solution into Visual Studio
  3. Run dotnet publish .\BuildTools\ from the root folder.
  4. Run dotnet msbuild .\Test.msbuild. This highlights the issue being raised and raises the exception shown below.

We are currently working around this problem by adding a global.json targeting the core 6.0 runtime and this can be demonstrated in the attached application by renaming the provided global.json.bak file. Before running the msbuild, start the WcfServiceLibrary so the service host is available and this will allow the mean the msbuild will run without error.

Exceptions (if any)

C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018: The "LoadTask" task failed unexpectedly.
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018: System.IO.FileLoadException: The given assembly name was invalid.
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018: File name: 'DispatchProxyTypes.MSBuild plugin C:\temp\DotNet7BuildBug\BuildTools\bin\Debug\net6.0\publish\BuildTools.dll'
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.ThrowInvalidAssemblyName()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.GetNextToken(String& tokenString)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.Parse()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyNameParser.Parse(String name)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.AssemblyName..ctor(String assemblyName)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxyGenerator.ProxyAssembly..ctor(AssemblyLoadContext alc)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxyGenerator.<>c.<CreateProxyInstance>b__6_0(AssemblyLoadContext x)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValueLocked(TKey key, CreateValueCallback createValueCallback)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxyGenerator.CreateProxyInstance(Type baseType, Type interfaceType)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.Reflection.DispatchProxy.Create[T,TProxy]()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.Channels.ServiceChannelProxy.CreateProxy[TChannel](MessageDirection direction,ServiceChannel serviceChannel)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.Channels.ServiceChannelFactory.CreateProxy[TChannel](MessageDirection direction, ServiceChannel serviceChannel)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.Channels.ServiceChannelFactory.CreateChannel[TChannel](EndpointAddress address, Uri via)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via)
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ChannelFactory`1.CreateChannel()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ClientBase`1.CreateChannel()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ClientBase`1.CreateChannelInternal()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at System.ServiceModel.ClientBase`1.get_Channel()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at ServiceReference1.Service1Client.GetDataAsync(Int32 value) in C:\temp\DotNet7BuildBug\BuildTools\Connected Services\ServiceReference1\Reference.cs:line 116
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at BuildTools.LoadTask.Execute() in C:\temp\DotNet7BuildBug\BuildTools\LoadTask.cs:line 10
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
C:\temp\DotNet7BuildBug\Test.msbuild(7,9): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

Further technical details

Output from dotnet --info:

.NET SDK:
 Version:   7.0.101
 Commit:    bb24aafa11

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\7.0.101\

Host:
  Version:      7.0.1
  Architecture: x64
  Commit:       97203d38ba

.NET SDKs installed:
  3.1.426 [C:\Program Files\dotnet\sdk]
  5.0.403 [C:\Program Files\dotnet\sdk]
  5.0.408 [C:\Program Files\dotnet\sdk]
  5.0.410 [C:\Program Files\dotnet\sdk]
  6.0.200 [C:\Program Files\dotnet\sdk]
  6.0.202 [C:\Program Files\dotnet\sdk]
  6.0.203 [C:\Program Files\dotnet\sdk]
  6.0.301 [C:\Program Files\dotnet\sdk]
  6.0.302 [C:\Program Files\dotnet\sdk]
  6.0.307 [C:\Program Files\dotnet\sdk]
  6.0.401 [C:\Program Files\dotnet\sdk]
  6.0.404 [C:\Program Files\dotnet\sdk]
  7.0.101 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.27 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.27 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.27 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

Visual Studio version information:

Microsoft Visual Studio Enterprise 2022
Version 17.4.3
VisualStudio.17.Release/17.4.3+33205.214
Microsoft .NET Framework
Version 4.8.04084

Installed Version: Enterprise

Visual C++ 2022   00476-80000-00000-AA277
Microsoft Visual C++ 2022

ADL Tools Service Provider   1.0
This package contains services used by Data Lake tools

ASA Service Provider   1.0

ASP.NET and Web Tools   17.4.326.54890
ASP.NET and Web Tools

Azure App Service Tools v3.0.0   17.4.326.54890
Azure App Service Tools v3.0.0

Azure Data Lake Tools for Visual Studio   2.6.5000.0
Microsoft Azure Data Lake Tools for Visual Studio

Azure Functions and Web Jobs Tools   17.4.326.54890
Azure Functions and Web Jobs Tools

Azure Stream Analytics Tools for Visual Studio   2.6.5000.0
Microsoft Azure Stream Analytics Tools for Visual Studio

C# Tools   4.4.0-6.22580.4+d7a61210a88b584ca0827585ec6e871c6b1c5a14
C# components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.

Common Azure Tools   1.10
Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.

File Differ   3.0.43
The easiest way to diff two files directly in Solution Explorer

File Icons   2.7
Adds icons for files that are not recognized by Solution Explorer

iMeta CLM Cdmu Editor   1.0
A Cdmu rule editor for iMeta CLM modules.

iMeta CLM Csx Rule Editor   1.0
A Csx rule editor for iMeta CLM modules.

iMeta CLM User Group Config Editor   1.0
Editor for iMeta CLM module User Group Configuration

Microsoft Azure Hive Query Language Service   2.6.5000.0
Language service for Hive query

Microsoft Azure Stream Analytics Language Service   2.6.5000.0
Language service for Azure Stream Analytics

Microsoft Azure Tools for Visual Studio   2.9
Support for Azure Cloud Services projects

Microsoft JVM Debugger   1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines

Node.js Tools   1.5.40817.1 Commit Hash:66443775f9f3b1d8f8fee47af5002828b346688d
Adds support for developing and debugging Node.js apps in Visual Studio

NuGet Package Manager   6.4.0
NuGet Package Manager in Visual Studio. For more information about NuGet, visit https://docs.nuget.org/

Razor (ASP.NET Core)   17.0.0.2246202+61cc048d36a3fc9246d2f04625988b19a18ab8f0
Provides languages services for ASP.NET Core Razor.

RuleVisualiserWindow Extension   1.0
RuleVisualiserWindow Visual Studio Extension Detailed Info

SQL Server Data Tools   17.0.62207.28050
Microsoft SQL Server Data Tools

SVG Viewer   1.0.16
Makes it much easier to work with SVG files by showing a live preview in the bottom-right corner of the code window

ToolWindowHostedEditor   1.0
Hosting json editor into a tool window

TypeScript Tools   17.0.10921.2001
TypeScript Tools for Microsoft Visual Studio

Visual Basic Tools   4.4.0-6.22580.4+d7a61210a88b584ca0827585ec6e871c6b1c5a14
Visual Basic components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.

Visual F# Tools   17.4.0-beta.22512.4+525d5109e389341bb90b144c24e2ad1ceec91e7b
Microsoft Visual F# Tools

Visual Studio Extension for SpecFlow   1.0
Visual Studio extension for working with SpecFlow projects and Gherkin feature files.

Visual Studio IntelliCode   2.2
AI-assisted development for Visual Studio.

VSColorOutput64   2022.2
Color output for build and debug windows - https://mike-ward.net/vscoloroutput
Author: philiphendry
Assignees: -
Labels:

area-System.Reflection, untriaged

Milestone: -

@buyaa-n buyaa-n added this to the 8.0.0 milestone Feb 11, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Feb 11, 2023
@buyaa-n
Copy link
Member

buyaa-n commented Feb 13, 2023

Thank you for the broad investigation @KalleOlaviNiemitalo, it seems we don't need to use the ALC name or hash for the builder name, can just use the same name ProxyBuilder for all ALC.

@KalleOlaviNiemitalo
Copy link

KalleOlaviNiemitalo commented Feb 13, 2023

Is it feasible to publish the AssemblyLoadContext.Name to debuggers in some other way, so that they can find it if they have a reference to the generated assembly?

AssemblyBuilder.DefineDynamicAssembly does not take an AssemblyLoadContext parameter, but it uses AssemblyLoadContext.CurrentContextualReflectionContext here:

[RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")]
[DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable.
public static AssemblyBuilder DefineDynamicAssembly(
AssemblyName name,
AssemblyBuilderAccess access,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
{
return InternalDefineDynamicAssembly(name,
access,
Assembly.GetCallingAssembly(),
AssemblyLoadContext.CurrentContextualReflectionContext,
assemblyAttributes);
}

So, DispatchPrpxy could use this API to place the generated assembly into the AssemblyLoadContext for which it was generated. However, I don't know what side effects that would have. Likely it's too risky for .NET 7.

Alternatively, DispatchProxy could generate an AssemblyMetadataAttribute that carries the AssemblyLoadContext.Name. That would have lower risk.

I don't know whether either of these would make it easy to view the ALC name in debuggers, especially in postmortem WinDbg + SOS.

@buyaa-n
Copy link
Member

buyaa-n commented Feb 18, 2023

So, DispatchPrpxy could use this API to place the generated assembly into the AssemblyLoadContext for which it was generated. However, I don't know what side effects that would have. Likely it's too risky for .NET 7.

Probably this should be fixed with #62234 not in DispatchProxy

Alternatively, DispatchProxy could generate an AssemblyMetadataAttribute that carries the AssemblyLoadContext.Name. That would have lower risk.

I would prefer replacing disallowed characters with underscores as you suggested above instead. I am still not sure how useful of having AssemblyLoadContext.Name as assembly name for debuggers. Though it seems there is no other way to know the custom ALC name, but I think that issue can be solved when #62234 is resolved

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants