Skip to content

With Faster Exceptions, exceptions thrown in some out-of-process COM calls raise AppDomain.CurrentDomain.UnhandledException #113367

Open
@Molinarius

Description

@Molinarius

Description

Probably starting with the faster exceptions of .NET 9, in an application that provides an out-of-process COM server, when a method that has been called from the COM client throws an exception, the first of these exceptions raises the event AppDomain.CurrentDomain.UnhandledException.

However, this happens only in some type of clients, my guess is clients that use IDispatch.

Reproduction Steps

  1. Get the out-of-process COM example from https://github.com/dotnet/samples/tree/main/core/extensions/OutOfProcCOM.

  2. Change the ExeServer project to use .NET9.

  3. In Program.cs of the project ExeServer, in Main, add these lines after the call of Trace.Listeners.Add:

    AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
        Trace.WriteLine($"CurrentDomain_UnhandledException: IsTerminating={e.IsTerminating}, {e.ExceptionObject}");
    Trace.WriteLine($"Environment.Version is {Environment.Version}, Is64BitProcess is {Environment.Is64BitProcess}.");
    Trace.WriteLine($"DOTNET_LegacyExceptionHandling is '{Environment.GetEnvironmentVariable("DOTNET_LegacyExceptionHandling")}'.");
    
  4. In ExeServer.cs, in the method double IServer.ComputePi(), add this line as second line:

    throw new OverflowException("This is not an actual overflow.");

  5. In the project ManagedClient in the file Program.cs, make these changes:

    • Replace the line var server = (IServer)obj; with dynamic server = obj;

    • Replace these lines:

      double pi = server.ComputePi();
      Console.WriteLine($"\u03C0 = {pi}");
      

      with:

      for (int i = 0; i < 3; i++)
      {
          try
          {
              double pi = server.ComputePi();
              Console.WriteLine($"\u03C0 = {pi}");
          }
          catch (Exception e)
          {
              Console.WriteLine(e.GetType() + " " + e.Message);
          }
      }
      
  6. Compile, COM register, and run ManagedClient as described in README.md.

  7. (Unregister when done.)

Expected behavior

AppDomain.CurrentDomain.UnhandledException is not raised.

Actual behavior

AppDomain.CurrentDomain.UnhandledException is raised, but only on the first exception.

Regression?

Yes. Works as expected with .NET 8, and works when setting the environment variable DOTNET_LegacyExceptionHandling to 1.

Known Workarounds

It currently seems to me that the call to UnhandledException has no side effects.

Therefore, I'm not sure if it actually might be a workaround to ignore such exceptions in handlers of UnhandledException, e.g. by somehow marking them.

Configuration

Windows 10 22H2.

.NET SDKs:

  • 9.0.200
  • 10.0.100-preview.1.25120.13

Other information

  • Same behavior with .NET 9 and .NET 10 preview.

  • I see the same behavior when using VB script, e.g.:

    ' Run with cscript
    set server = GetObject("new:{AF080472-F173-4D9D-8BE7-435776617347}")
    on error resume next
    Dim i
    For i = 1 To 3
        Dim result
        result = server.ComputePi()
    
        If Err.Number <> 0 Then
            WScript.Echo "Error: " & Err.Description
            Err.Clear
        Else
            WScript.Echo "result: " & result
        End If
    Next
    
  • When using PowerShell, both the Windows PowerShell and pwsh, I see the same behavior with other projects, however, with this example project, creating a COM object gives me the error Type library is not registered. (0x80131165), but I think this is a different topic.

  • I do not see this behavior with the NativeClient of this example project, and not with native clients using #import, and not with the unmodified ManagedClient of this example project.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions