diff --git a/eng/verify-nupkgs.ps1 b/eng/verify-nupkgs.ps1 index c6417b4f10..51a5719fbc 100644 --- a/eng/verify-nupkgs.ps1 +++ b/eng/verify-nupkgs.ps1 @@ -20,7 +20,7 @@ function Verify-Nuget-Packages { "Microsoft.CodeCoverage" = 76 "Microsoft.NET.Test.Sdk" = 26 "Microsoft.TestPlatform" = 545 - "Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI" = 388 + "Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI" = 389 "Microsoft.TestPlatform.Build" = 21 "Microsoft.TestPlatform.CLI" = 483 "Microsoft.TestPlatform.Extensions.TrxLogger" = 35 diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj index 7bc1805000..a907eb85ff 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/common/NativeMethods.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/common/NativeMethods.cs index e75a249168..0d9fdd9d20 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/common/NativeMethods.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/common/NativeMethods.cs @@ -9,11 +9,6 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; internal class NativeMethods { public const ushort IMAGE_FILE_MACHINE_ARM64 = 0xAA64; - public const ushort IMAGE_FILE_MACHINE_UNKNOWN = 0; - - [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsWow64Process2([In] IntPtr process, [Out] out ushort processMachine, [Out] out ushort nativeMachine); // A pointer to a value that is set to TRUE if the process is running under WOW64. // If the process is running under 32-bit Windows, the value is set to FALSE. diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/PlatformEnvironment.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/PlatformEnvironment.cs index 09fb1ea528..fecb20fcf6 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/PlatformEnvironment.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/PlatformEnvironment.cs @@ -4,8 +4,7 @@ #if NETFRAMEWORK || NETSTANDARD2_0 using System; -using System.ComponentModel; -using System.Diagnostics; +using System.Runtime.InteropServices; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; @@ -21,38 +20,15 @@ public PlatformArchitecture Architecture { get { - return _architecture ??= Environment.Is64BitOperatingSystem - ? IsArm64() - ? PlatformArchitecture.ARM64 - : PlatformArchitecture.X64 - : PlatformArchitecture.X86; - } - } - - private static bool IsArm64() - { - try - { - var currentProcess = Process.GetCurrentProcess(); - if (!NativeMethods.IsWow64Process2(currentProcess.Handle, out ushort _, out ushort nativeMachine)) + return _architecture ??= RuntimeInformation.OSArchitecture switch { - throw new Win32Exception(); - } - - // If nativeMachine is IMAGE_FILE_MACHINE_ARM64 it means that we're running on ARM64 architecture device. - return nativeMachine == NativeMethods.IMAGE_FILE_MACHINE_ARM64; - } - catch - { - // At the moment we cannot log messages inside the Microsoft.TestPlatform.PlatformAbstractions. - // We did an attempt in https://github.com/microsoft/vstest/pull/3422 - 17.2.0-preview-20220301-01 - but we reverted after - // because we broke a scenario where for .NET Framework application inside the test host - // we loaded runner version of Microsoft.TestPlatform.PlatformAbstractions but newer version Microsoft.TestPlatform.ObjectModel(the one close - // to the test container) and the old PlatformAbstractions doesn't contain the methods expected by the new ObjectModel throwing - // a MissedMethodException. + System.Runtime.InteropServices.Architecture.X86 => PlatformArchitecture.X86, + System.Runtime.InteropServices.Architecture.X64 => PlatformArchitecture.X64, + System.Runtime.InteropServices.Architecture.Arm => PlatformArchitecture.ARM, + System.Runtime.InteropServices.Architecture.Arm64 => PlatformArchitecture.ARM64, + _ => throw new NotSupportedException(), + }; } - - return false; } /// diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/ProcessHelper.cs index ffb9c38bfa..35e5fa940c 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/net462/System/ProcessHelper.cs @@ -2,12 +2,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.ComponentModel; using System.Diagnostics; using System.IO; -# if NETCOREAPP || NETSTANDARD2_0_OR_GREATER using System.Runtime.InteropServices; -#endif + using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; @@ -15,8 +13,6 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; public partial class ProcessHelper : IProcessHelper { #if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER - private PlatformArchitecture? _currentProcessArchitecture; - /// public string GetCurrentProcessLocation() => Path.GetDirectoryName(GetCurrentProcessFileName()); @@ -30,22 +26,14 @@ public nint GetProcessHandle(int processId) => /// public PlatformArchitecture GetCurrentProcessArchitecture() { - // If we already cached the current process architecture, no need to figure it out again. - if (_currentProcessArchitecture is not null) - { - return _currentProcessArchitecture.Value; - } - - // When this is current process, we can just check if IntPointer size to get if we are 64-bit or 32-bit. - // When it is 32-bit we can just return, if it is 64-bit we need to clarify if x64 or arm64. - if (IntPtr.Size == 4) + return RuntimeInformation.ProcessArchitecture switch { - _currentProcessArchitecture = PlatformArchitecture.X86; - return _currentProcessArchitecture.Value; - } - - _currentProcessArchitecture ??= GetProcessArchitecture(_currentProcess.Id); - return _currentProcessArchitecture.Value; + Architecture.X86 => PlatformArchitecture.X86, + Architecture.X64 => PlatformArchitecture.X64, + Architecture.Arm => PlatformArchitecture.ARM, + Architecture.Arm64 => PlatformArchitecture.ARM64, + _ => throw new NotSupportedException(), + }; } #endif @@ -60,76 +48,48 @@ public PlatformArchitecture GetProcessArchitecture(int processId) } #endif - // If the current process is 64-bit, or this is any remote process, we need to query it via native api. - var process = processId == _currentProcess.Id ? _currentProcess : Process.GetProcessById(processId); + // For the current process, use RuntimeInformation directly. + if (processId == _currentProcess.Id) + { + return GetCurrentProcessArchitecture(); + } + + // For remote processes, we need Windows APIs. + var process = Process.GetProcessById(processId); try { - if (!NativeMethods.IsWow64Process2(process.Handle, out ushort processMachine, out ushort nativeMachine)) + if (!Environment.Is64BitOperatingSystem) { - throw new Win32Exception(); + return PlatformArchitecture.X86; } - if (processMachine != NativeMethods.IMAGE_FILE_MACHINE_UNKNOWN) + var isWow64Succeeded = NativeMethods.IsWow64Process(process.Handle, out var isWow64); + if (isWow64Succeeded && isWow64) { - // The process is running using WOW64, which suggests it is 32-bit (or any of the other machines, that we cannot - // handle, so we just assume x86). + // The process is running using WOW64, which means it is 32-bit. return PlatformArchitecture.X86; } - // If processMachine is IMAGE_FILE_MACHINE_UNKNOWN mean that we're not running using WOW64 emulation. - // If nativeMachine is IMAGE_FILE_MACHINE_ARM64 mean that we're running on ARM64 architecture device. - if (processMachine == NativeMethods.IMAGE_FILE_MACHINE_UNKNOWN && nativeMachine == NativeMethods.IMAGE_FILE_MACHINE_ARM64) + // Not WOW64 — this is a native 64-bit process. + // On ARM64 OS, distinguish ARM64 native from x64 emulated via the PE header. + if (RuntimeInformation.OSArchitecture == Architecture.Arm64) { - // To distinguish between ARM64 and x64 emulated on ARM64 we check the PE header of the current running executable. - if (IsArm64Executable(process.MainModule!.FileName)) - { - return PlatformArchitecture.ARM64; - } - else - { - return PlatformArchitecture.X64; - } - } - else - { - return PlatformArchitecture.X64; + return IsArm64Executable(process.MainModule!.FileName) + ? PlatformArchitecture.ARM64 + : PlatformArchitecture.X64; } + + return PlatformArchitecture.X64; } catch { - // At the moment we cannot log messages inside the Microsoft.TestPlatform.PlatformAbstractions. - // We did an attempt in https://github.com/microsoft/vstest/pull/3422 - 17.2.0-preview-20220301-01 - but we reverted after - // because we broke a scenario where for .NET Framework application inside the test host - // we loaded runner version of Microsoft.TestPlatform.PlatformAbstractions but newer version Microsoft.TestPlatform.ObjectModel(the one close - // to the test container) and the old PlatformAbstractions doesn't contain the methods expected by the new ObjectModel throwing - // a MissedMethodException. - if (!Environment.Is64BitOperatingSystem) { - // When we know this is not 64-bit operating system, then all processes are running as 32-bit, both - // the current process and other processes. return PlatformArchitecture.X86; } - try - { - var isWow64Process = NativeMethods.IsWow64Process(process.Handle, out var isWow64); - if (!isWow64Process) - { - // Do nothing we cannot log errors here. - } - - // The process is running using WOW64, which suggests it is 32-bit (or any of the other machines, that we cannot - // handle, so we just assume x86). If it is not wow, we assume x64, because we failed the call to more advanced api - // that can tell us if this is arm64, so we are probably on older version of OS which is x64. - // We could call PlatformArchitecture.Architecture, but that uses the same api that we just failed to invoke. - return isWow64 ? PlatformArchitecture.X86 : PlatformArchitecture.X64; - } - catch - { - // We are on 64-bit system, let's assume x64 when we fail to determine the value. - return PlatformArchitecture.X64; - } + // We are on 64-bit system, let's assume x64 when we fail to determine the value. + return PlatformArchitecture.X64; } }