-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathManagedProfilerAssemblyResolver.NetFramework.cs
More file actions
81 lines (67 loc) · 3.32 KB
/
Copy pathManagedProfilerAssemblyResolver.NetFramework.cs
File metadata and controls
81 lines (67 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// <copyright file="ManagedProfilerAssemblyResolver.NetFramework.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>
#if NETFRAMEWORK
#nullable enable
using System;
using System.IO;
using System.Reflection;
namespace Datadog.Trace.ClrProfiler.Managed.Loader;
// Owns the AppDomain.AssemblyResolve callback on .NET Framework. Kept on a
// separate class from Startup so the handler can be dispatched without
// forcing Startup's type-initializer to have finished. If the handler were
// a method on Startup, a configBuilder attached to <appSettings> that
// issues sync-over-async work during Startup..cctor could deadlock: the
// main thread would be blocked inside the .cctor waiting for a Task, whose
// continuation runs on a ThreadPool thread that probes Type.GetType and
// fires AssemblyResolve, whose handler would then wait on Startup..cctor.
internal static class ManagedProfilerAssemblyResolver
{
// Seeded by Startup..cctor before the handler is subscribed.
internal static string? ManagedProfilerDirectory { get; set; }
internal static Assembly? OnAssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
return ResolveAssembly(args.Name);
}
catch (Exception ex)
{
StartupLogger.Log(ex, "Error resolving assembly: {0}", args.Name);
}
return null;
}
internal static Assembly? ResolveAssembly(string name)
{
var assemblyName = new AssemblyName(name);
// On .NET Framework, having a non-US locale can cause mscorlib
// to enter the AssemblyResolve event when searching for resources
// in its satellite assemblies. Exit early so we don't cause
// infinite recursion.
if (string.Equals(assemblyName.Name, "mscorlib.resources", StringComparison.OrdinalIgnoreCase) ||
string.Equals(assemblyName.Name, "System.Net.Http", StringComparison.OrdinalIgnoreCase) ||
string.Equals(assemblyName.Name, "vstest.console.resources", StringComparison.OrdinalIgnoreCase))
{
return null;
}
// WARNING: Logs must not be added _before_ we check for the above bail-out conditions
var path = string.IsNullOrEmpty(ManagedProfilerDirectory) ? $"{assemblyName.Name}.dll" : Path.Combine(ManagedProfilerDirectory, $"{assemblyName.Name}.dll");
StartupLogger.Debug("Assembly Resolve event received for: {0}. Looking for: {1}", name, path);
if (File.Exists(path))
{
if (name.StartsWith("Datadog.Trace, Version=", StringComparison.Ordinal) && name != Startup.AssemblyName)
{
StartupLogger.Debug(" Trying to load '{0}' which does not match the expected version ('{1}'). [Path={2}]", name, Startup.AssemblyName, path);
return null;
}
StartupLogger.Debug("Calling Assembly.LoadFrom(\"{0}\")", path);
var assembly = Assembly.LoadFrom(path);
StartupLogger.Debug("Assembly loaded: {0}", assembly.FullName);
return assembly;
}
StartupLogger.Debug("Assembly not found in path: {0}", path);
return null;
}
}
#endif