in src/Microsoft.TestPlatform.ObjectModel/Utilities/AssemblyLoadWorker.cs [169:266]
public void GetPlatformAndFrameworkSettings(string path, out string procArchType, out string frameworkVersion)
{
procArchType = nameof(Architecture.Default);
frameworkVersion = String.Empty;
try
{
// ReflectionOnlyLoadFrom does not use the probing paths and loads from the
// specified path only and does not let code to be executed by the assembly
// in the loaded context.
var a = Assembly.ReflectionOnlyLoadFrom(path);
Debug.Assert(a != null);
a.ManifestModule.GetPEKind(out var peKind, out var machine);
// conversion to string type is needed for below reason
// -- PortableExecutableKinds.Preferred32Bit and ImageFileMachine.ARM is available only
// in .Net4.0 and above. Below code is compiled with .Net3.5 but runs in .Net4.0
string peKindString = peKind.ToString();
string machineTypeString = machine.ToString();
if (string.Equals(machineTypeString, "I386", StringComparison.OrdinalIgnoreCase))
{
if (peKindString.Contains("Preferred32Bit") || peKindString.Contains("Required32Bit"))
{
procArchType = "X86";
}
else if (string.Equals(peKindString, "ILOnly", StringComparison.OrdinalIgnoreCase))
{
procArchType = "AnyCPU";
}
}
else if (string.Equals(machineTypeString, "AMD64", StringComparison.OrdinalIgnoreCase) ||
string.Equals(machineTypeString, "IA64", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(peKindString, "ILOnly, PE32Plus", StringComparison.OrdinalIgnoreCase))
{
procArchType = "X64";
}
}
else if (string.Equals(machineTypeString, "ARM", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(peKindString, "ILOnly", StringComparison.OrdinalIgnoreCase))
{
procArchType = "ARM";
}
}
if (string.IsNullOrEmpty(procArchType))
{
if (EqtTrace.IsVerboseEnabled)
{
EqtTrace.Verbose("Unable to find the platform type for image:{0} with PEKind:{1}, Machine:{2}. Returning Default:{3}", path, peKindString, machineTypeString, "AnyCPU");
}
procArchType = "AnyCPU";
}
frameworkVersion = a.ImageRuntimeVersion.Substring(0, 4).ToUpperInvariant();
// ImageRuntimeVersion for v4.0 & v4.5 are same and it return v4.0
// Since there is behavioral difference in both its important to differentiate them
// Using TargetFrameworkAttribute for the purpose.
if (string.Equals(frameworkVersion, "v4.0", StringComparison.OrdinalIgnoreCase))
{
// Try to determine the exact .NET framework by inspecting custom attributes on assembly.
string dotNetVersion = GetTargetFrameworkStringFromAssembly(a);
if (dotNetVersion.StartsWith(Constants.DotNetFramework40, StringComparison.OrdinalIgnoreCase))
{
frameworkVersion = "v4.0";
}
else if (dotNetVersion.StartsWith(Constants.DotNetFramework45, StringComparison.OrdinalIgnoreCase))
{
frameworkVersion = "v4.5";
}
else if (dotNetVersion.Length > Constants.DotNetFrameWorkStringPrefix.Length)
{
frameworkVersion = dotNetVersion.Substring(Constants.DotNetFrameWorkStringPrefix.Length);
}
}
}
catch (BadImageFormatException)
{
if (EqtTrace.IsErrorEnabled)
{
EqtTrace.Error("AssemblyLoadWorker:GetPlatformAndFrameworkSettings() caught BadImageFormatException. Falling to native binary.");
}
procArchType = GetArchitectureForSource(path);
}
catch (Exception ex)
{
if (EqtTrace.IsErrorEnabled)
{
EqtTrace.Error("AssemblyLoadWorker:GetPlatformAndFrameworkSettings() Returning default. Unhandled exception: {0}.", ex);
}
return;
}
}