Skip to content

.NET 8 fails to load System.Security.Permissions when dynamically loading plugin that references Framework #104587

Open
@yaakov-h

Description

@yaakov-h

Description

I need to remotely administer an IIS server, and Microsoft.Web.Administration is a long-standing solution which manages this via remote COM APIs.

The latest versions of Microsoft.Web.Administration ships for .NET Standard, but these builds have the remote-administration code compiled out, and instead just throw a NullReferenceException from ServerManager.OpenRemote.

The older version 7.0 of Microsoft.Web.Administration only ships for .NET Framework 2.0, but it works on .NET 8 if we supply System.Security.Permissions as well via NuGet.

However, the .NET 8 runtime fails to load System.Security.Permissions when operating inside of another AssemblyLoadContext. It only seems to succeed if the entrypoint project is what takes on the package references.

When debugging this the runtime does not even ask for System.Security.Permissions.dll. I cannot find anything from a dotnet-trace to explain why it is failing, and procmon64 suggests that the .NET Runtime does not even look for the file on disk, it just aborts early with an exception.

Reproduction Steps

On a Windows machine with IIS and the .NET 8 SDK installed:

  1. Clone https://github.com/yaakov-h/dotnet-repro-remote-webadmin
  2. Create the folder 'bin'
  3. cd bin
  4. .\repro.ps1 from PowerShell as Administrator (elevated)

Expected behavior

The script displays success in all 5 scenarios:

  • Initial build, loading using Assembly.Load
  • Initial build, loading using AssemblyLoadContext
  • Rebuild with additional reference, loading using Assembly.Load
  • Rebuild with additional reference, loading using AssemblyLoadContext
  • Rebuild with additional reference, loading using Type.GetType()

Actual behavior

The first two scenarios fail, the final three pass:

PS> .\repro.ps1

Building project...
  Determining projects to restore...
  Restored C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\PluginHost\PluginHost.csproj (in 70 ms).
  2 of 3 projects are up-to-date for restore.
  PluginInterfaces -> C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\PluginInterfaces.dll
  RemoteWebAdministrationPlugin -> C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\plugins\RemoteWebAdministrationPlugin.dll
  PluginHost -> C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\PluginHost.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.84

Running with Assembly.Load...
AppDomain.CurrentDomain.AssemblyResolve: Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
AppDomain.CurrentDomain.AssemblyResolve: System.Security.Permissions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'System.Security.Permissions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
File name: 'System.Security.Permissions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
   at Microsoft.Web.Administration.Configuration.CheckPermissions(IAppHostElement section)
   at Microsoft.Web.Administration.Configuration.GetSectionInternal(ConfigurationSection section, String sectionPath, String locationPath)
   at Microsoft.Web.Administration.Configuration.GetSection(String sectionPath)
   at Microsoft.Web.Administration.ServerManager.get_SitesSection()
   at Microsoft.Web.Administration.ServerManager.get_Sites()
   at RemoteWebAdministrationPlugin.ListRemoteIisSitesPlugin.DoSomething(String[] args) in C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\RemoteWebAdministrationPlugin\ListRemoteIisSitesPlugin.cs:line 19
   at Program.<Main>$(String[] args) in C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\PluginHost\Program.cs:line 53

Running with AssemblyLoadContext...
PluginLoadContext.Load: Loading RemoteWebAdministrationPlugin from C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\plugins\RemoteWebAdministrationPlugin.dll
PluginLoadContext.Load: System.Runtime failed to resolve to path
PluginLoadContext.Load: PluginInterfaces loading from default context.
PluginLoadContext.Load: Loading Microsoft.Web.Administration from C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\plugins\Microsoft.Web.Administration.dll
PluginLoadContext.Load: mscorlib failed to resolve to path
PluginLoadContext.Load: System.Console failed to resolve to path
PluginLoadContext.Load: System failed to resolve to path
PluginLoadContext.LoadUnmanagedDll: ole32.dll failed to resolve to path
PluginLoadContext.Load: System.Configuration failed to resolve to path
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'System.Security.Permissions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
File name: 'System.Security.Permissions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
   at Microsoft.Web.Administration.Configuration.CheckPermissions(IAppHostElement section)
   at Microsoft.Web.Administration.Configuration.GetSectionInternal(ConfigurationSection section, String sectionPath, String locationPath)
   at Microsoft.Web.Administration.Configuration.GetSection(String sectionPath)
   at Microsoft.Web.Administration.ServerManager.get_SitesSection()
   at Microsoft.Web.Administration.ServerManager.get_Sites()
   at RemoteWebAdministrationPlugin.ListRemoteIisSitesPlugin.DoSomething(String[] args) in C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\RemoteWebAdministrationPlugin\ListRemoteIisSitesPlugin.cs:line 19
   at Program.<Main>$(String[] args) in C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\PluginHost\Program.cs:line 53

Rebuilding project with ProjectReference...
  Determining projects to restore...
  Restored C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\PluginHost\PluginHost.csproj (in 201 ms).
  2 of 3 projects are up-to-date for restore.
  PluginInterfaces -> C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\PluginInterfaces.dll
  RemoteWebAdministrationPlugin -> C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\plugins\RemoteWebAdministrationPlugin.dll
  PluginHost -> C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\PluginHost.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.97

Running with Assembly.Load...
Server '5FKTZT3' has 5 sites hosted in IIS.

Running with AssemblyLoadContext...
PluginLoadContext.Load: Loading RemoteWebAdministrationPlugin from C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\plugins\RemoteWebAdministrationPlugin.dll
PluginLoadContext.Load: System.Runtime failed to resolve to path
PluginLoadContext.Load: PluginInterfaces loading from default context.
PluginLoadContext.Load: Loading Microsoft.Web.Administration from C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\bin\plugins\Microsoft.Web.Administration.dll
PluginLoadContext.Load: mscorlib failed to resolve to path
PluginLoadContext.Load: System.Console failed to resolve to path
PluginLoadContext.Load: System failed to resolve to path
PluginLoadContext.LoadUnmanagedDll: ole32.dll failed to resolve to path
PluginLoadContext.Load: System.Configuration failed to resolve to path
Server '5FKTZT3' has 5 sites hosted in IIS.

Running with direct Type.GetType...
Server '5FKTZT3' has 5 sites hosted in IIS.

Regression?

This worked using Assembly.Load in .NET Framework. likely due to System.Security.Permissions being part of the BCL.

Known Workarounds

Adding a direct reference from the plugin host to the plugin project seems to work as a workaround, though I have absolutely no idea why. This is also not a viable permanent/long term workaround, more of a strange oddity discovered whilst trying to reproduce the issue.

Additionally, using AppDomain.CurrentDomain.AssemblyResolve hook as shown here appears to be a workaround, but this seems to break the purpose and spirit of using AssemblyLoadContext.

Configuration

dotnet --info:

.NET SDK:
 Version:           8.0.300
 Commit:            326f6e68b2
 Workload version:  8.0.300-manifests.9e3391ed
 MSBuild version:   17.10.4+10fbfbf2e

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22631
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.300\

.NET workloads installed:
 [maui-windows]
   Installation Source: VS 17.10.34916.146
   Manifest Version:    8.0.21/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.maui\8.0.21\WorkloadManifest.json
   Install Type:              Msi

 [ios]
   Installation Source: VS 17.10.34916.146
   Manifest Version:    17.2.8053/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.ios\17.2.8053\WorkloadManifest.json
   Install Type:              Msi

 [maccatalyst]
   Installation Source: VS 17.10.34916.146
   Manifest Version:    17.2.8053/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.maccatalyst\17.2.8053\WorkloadManifest.json
   Install Type:              Msi

 [aspire]
   Installation Source: VS 17.10.34916.146
   Manifest Version:    8.0.0/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.0.0\WorkloadManifest.json
   Install Type:              Msi

 [android]
   Installation Source: VS 17.10.34916.146
   Manifest Version:    34.0.95/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.android\34.0.95\WorkloadManifest.json
   Install Type:              Msi


Host:
  Version:      9.0.0-preview.5.24306.7
  Architecture: x64
  Commit:       a5cc707d97

.NET SDKs installed:
  6.0.321 [C:\Program Files\dotnet\sdk]
  6.0.423 [C:\Program Files\dotnet\sdk]
  7.0.120 [C:\Program Files\dotnet\sdk]
  7.0.317 [C:\Program Files\dotnet\sdk]
  7.0.410 [C:\Program Files\dotnet\sdk]
  8.0.106 [C:\Program Files\dotnet\sdk]
  8.0.300 [C:\Program Files\dotnet\sdk]
  9.0.100-preview.5.24307.3 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.31 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.0-preview.5.24306.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.31 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.0-preview.5.24306.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.30 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.31 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.19 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 9.0.0-preview.5.24306.8 [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:
  C:\git\GitHub\yaakov-h\dotnet-repro-remote-webadmin\global.json

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

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

N.B. this also fails on machines w/o .NET 9 previews.

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions