diff --git a/TestPlatform.sln b/TestPlatform.sln index f7a5b0292e..87ae9693fe 100644 --- a/TestPlatform.sln +++ b/TestPlatform.sln @@ -164,6 +164,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.Adap EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.TestPlatform.Execution.Shared", "src\Microsoft.TestPlatform.Execution.Shared\Microsoft.TestPlatform.Execution.Shared.shproj", "{7F26EDA3-C8C4-4B7F-A9B6-D278C2F40A13}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DumpMinitool", "src\DataCollectors\DumpMinitool\DumpMinitool.csproj", "{33A20B85-7024-4112-B1E7-00CD0E4A9F96}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DumpMinitool.x86", "src\DataCollectors\DumpMinitool.x86\DumpMinitool.x86.csproj", "{2C88C923-3D7A-4492-9241-7A489750CAB7}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Microsoft.TestPlatform.Execution.Shared\Microsoft.TestPlatform.Execution.Shared.projitems*{10b6ade1-f808-4612-801d-4452f5b52242}*SharedItemsImports = 5 @@ -793,6 +797,30 @@ Global {2DE99835-A3A3-4922-82AD-6D10D284816D}.Release|x64.Build.0 = Release|Any CPU {2DE99835-A3A3-4922-82AD-6D10D284816D}.Release|x86.ActiveCfg = Release|Any CPU {2DE99835-A3A3-4922-82AD-6D10D284816D}.Release|x86.Build.0 = Release|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Debug|x64.ActiveCfg = Debug|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Debug|x64.Build.0 = Debug|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Debug|x86.ActiveCfg = Debug|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Debug|x86.Build.0 = Debug|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Release|Any CPU.Build.0 = Release|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Release|x64.ActiveCfg = Release|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Release|x64.Build.0 = Release|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Release|x86.ActiveCfg = Release|Any CPU + {33A20B85-7024-4112-B1E7-00CD0E4A9F96}.Release|x86.Build.0 = Release|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Debug|x64.ActiveCfg = Debug|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Debug|x64.Build.0 = Debug|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Debug|x86.ActiveCfg = Debug|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Debug|x86.Build.0 = Debug|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Release|Any CPU.Build.0 = Release|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Release|x64.ActiveCfg = Release|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Release|x64.Build.0 = Release|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Release|x86.ActiveCfg = Release|Any CPU + {2C88C923-3D7A-4492-9241-7A489750CAB7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -862,6 +890,8 @@ Global {DCD0C39E-C78C-4A44-B0BD-7325254A2E97} = {376C19DE-31E2-4FF6-88FC-0D0D6233C999} {2DE99835-A3A3-4922-82AD-6D10D284816D} = {7D4082EA-7AC9-4DFB-98E8-C5E08BDC0EC3} {7F26EDA3-C8C4-4B7F-A9B6-D278C2F40A13} = {ED0C35EB-7F31-4841-A24F-8EB708FFA959} + {33A20B85-7024-4112-B1E7-00CD0E4A9F96} = {B705537C-B82C-4A30-AFA5-6244D9A7DAEB} + {2C88C923-3D7A-4492-9241-7A489750CAB7} = {B705537C-B82C-4A30-AFA5-6244D9A7DAEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0541B30C-FF51-4E28-B172-83F5F3934BCD} diff --git a/scripts/build.ps1 b/scripts/build.ps1 index d69c552b71..65980a0555 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -397,8 +397,21 @@ function Publish-Package $blameDataCollectorNetStandard = Join-Path $blameDataCollector $TPB_TargetFrameworkStandard Copy-Item $blameDataCollectorNetFull\Microsoft.TestPlatform.Extensions.BlameDataCollector.dll $fullCLRExtensionsDir -Force Copy-Item $blameDataCollectorNetFull\Microsoft.TestPlatform.Extensions.BlameDataCollector.pdb $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetFull\DumpMinitool.exe $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetFull\DumpMinitool.pdb $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetFull\DumpMinitool.exe.config $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetFull\DumpMinitool.x86.exe $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetFull\DumpMinitool.x86.pdb $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetFull\DumpMinitool.x86.exe.config $fullCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\Microsoft.TestPlatform.Extensions.BlameDataCollector.dll $coreCLRExtensionsDir -Force Copy-Item $blameDataCollectorNetStandard\Microsoft.TestPlatform.Extensions.BlameDataCollector.pdb $coreCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\DumpMinitool.exe $coreCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\DumpMinitool.pdb $coreCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\DumpMinitool.exe.config $coreCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\DumpMinitool.x86.exe $coreCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\DumpMinitool.x86.pdb $coreCLRExtensionsDir -Force + Copy-Item $blameDataCollectorNetStandard\DumpMinitool.x86.exe.config $coreCLRExtensionsDir -Force # we use this to dump processes on netcore Copy-Item $blameDataCollectorNetStandard\Microsoft.Diagnostics.NETCore.Client.dll $coreCLRExtensionsDir -Force diff --git a/scripts/verify-nupkgs.ps1 b/scripts/verify-nupkgs.ps1 index 4b887182c3..e2c3050634 100644 --- a/scripts/verify-nupkgs.ps1 +++ b/scripts/verify-nupkgs.ps1 @@ -14,13 +14,13 @@ function Verify-Nuget-Packages($packageDirectory, $version) $expectedNumOfFiles = @{ "Microsoft.CodeCoverage" = 59; "Microsoft.NET.Test.Sdk" = 27; - "Microsoft.TestPlatform" = 484; + "Microsoft.TestPlatform" = 488; "Microsoft.TestPlatform.Build" = 21; - "Microsoft.TestPlatform.CLI" = 367; + "Microsoft.TestPlatform.CLI" = 371; "Microsoft.TestPlatform.Extensions.TrxLogger" = 35; "Microsoft.TestPlatform.ObjectModel" = 238; "Microsoft.TestPlatform.AdapterUtilities" = 62; - "Microsoft.TestPlatform.Portable" = 596; + "Microsoft.TestPlatform.Portable" = 604; "Microsoft.TestPlatform.TestHost" = 214; "Microsoft.TestPlatform.TranslationLayer" = 123; } @@ -46,9 +46,8 @@ function Verify-Nuget-Packages($packageDirectory, $version) foreach($unzipNugetPackageDir in $unzipNugetPackageDirs) { $actualNumOfFiles = (Get-ChildItem -Recurse -File -Path $unzipNugetPackageDir).Count - $versionLen = $TPB_Version.Length + 1 # +1 for dot + $versionLen = $version.Length + 1 # +1 for dot $packageKey = (Get-Item $unzipNugetPackageDir).BaseName -replace ".{$versionLen}$" - Write-VerboseLog "verifying package $packageKey." if( $expectedNumOfFiles[$packageKey] -ne $actualNumOfFiles) diff --git a/scripts/verify-sign.ps1 b/scripts/verify-sign.ps1 index 3cf75f485b..98d437db01 100644 --- a/scripts/verify-sign.ps1 +++ b/scripts/verify-sign.ps1 @@ -30,7 +30,14 @@ $env:TP_TOOLS_DIR = Join-Path $env:TP_ROOT_DIR "tools" Write-Verbose "Setup build configuration." $TPB_SignCertificate = $Certificate $TPB_Configuration = $Configuration -$TPB_AssembliesPattern = @("*test*.dll", "*qualitytools*.dll", "*test*.exe", "*datacollector*.dll", "*datacollector*.exe", "QTAgent*.exe", "Microsoft.VisualStudio*.dll", "Microsoft.TestPlatform.Build.dll", "Microsoft.DiaSymReader.dll", "Microsoft.IntelliTrace*.dll", "concrt140.dll", "msvcp140.dll", "vccorlib140.dll", "vcruntime140.dll", "codecoveragemessages.dll", "covrun32.dll", "msdia140.dll", "covrun64.dll", "IntelliTrace.exe", "ProcessSnapshotCleanup.exe", "TDEnvCleanup.exe", "CodeCoverage.exe", "Microsoft.ShDocVw.dll", "UIAComwrapper.dll", "Interop.UIAutomationClient.dll", "SettingsMigrator.exe", "Newtonsoft.Json.dll") +$TPB_AssembliesPattern = @( + "*test*.dll", "*qualitytools*.dll", "*test*.exe", "*datacollector*.dll", "*datacollector*.exe", + "QTAgent*.exe", "Microsoft.VisualStudio*.dll", "Microsoft.TestPlatform.Build.dll", "Microsoft.DiaSymReader.dll", + "Microsoft.IntelliTrace*.dll", "concrt140.dll", "msvcp140.dll", "vccorlib140.dll", "vcruntime140.dll", "codecoveragemessages.dll", + "covrun32.dll", "msdia140.dll", "covrun64.dll", "IntelliTrace.exe", "ProcessSnapshotCleanup.exe", "TDEnvCleanup.exe", + "CodeCoverage.exe", "Microsoft.ShDocVw.dll", "UIAComwrapper.dll", "Interop.UIAutomationClient.dll", "SettingsMigrator.exe", + "Newtonsoft.Json.dll", "DumpMinitool*.exe" +) function Verify-Assemblies { diff --git a/src/DataCollectors/DumpMinitool.x86/DumpMinitool.x86.csproj b/src/DataCollectors/DumpMinitool.x86/DumpMinitool.x86.csproj new file mode 100644 index 0000000000..1aa9424397 --- /dev/null +++ b/src/DataCollectors/DumpMinitool.x86/DumpMinitool.x86.csproj @@ -0,0 +1,26 @@ + + + + ..\..\..\ + false + true + + + + net451 + net6.0 + true + AnyCPU + true + Exe + false + win7-x86 + false + + + + + + + + diff --git a/src/DataCollectors/DumpMinitool/DumpMinitool.csproj b/src/DataCollectors/DumpMinitool/DumpMinitool.csproj new file mode 100644 index 0000000000..9188916188 --- /dev/null +++ b/src/DataCollectors/DumpMinitool/DumpMinitool.csproj @@ -0,0 +1,22 @@ + + + + ..\..\..\ + false + true + + + + net451 + net6.0 + true + AnyCPU + false + Exe + false + win7-x86 + false + + + + diff --git a/src/DataCollectors/DumpMinitool/Program.cs b/src/DataCollectors/DumpMinitool/Program.cs new file mode 100644 index 0000000000..815cf6bfa9 --- /dev/null +++ b/src/DataCollectors/DumpMinitool/Program.cs @@ -0,0 +1,173 @@ +using Microsoft.Win32.SafeHandles; +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; + +namespace DumpMinitool +{ + internal class Program + { + static int Main(string[] args) + { + DebuggerBreakpoint.WaitForDebugger("VSTEST_DUMPTOOL_DEBUG"); + Console.WriteLine($"Dump minitool: Started with arguments {string.Join(" ", args)}"); + if (args?.Length != 6) + { + Console.WriteLine($"There were { args?.Length ?? 0 } parameters. Provide exactly 6 parameters: --file --processId --dumpType "); + return 2; + } + + var outputFile = args[1]; + var processId = int.Parse(args[3]); + var type = Enum.Parse(typeof(DumpTypeOption), args[5]); + + Console.WriteLine($"Output file: '{outputFile}'"); + Console.WriteLine($"Process id: {processId}"); + Console.WriteLine($"Dump type: {type}"); + + var process = Process.GetProcessById(processId); + + using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) + { + NativeMethods.MINIDUMP_EXCEPTION_INFORMATION exceptionInfo = default; + + NativeMethods.MINIDUMP_TYPE dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal; + switch (type) + { + case DumpTypeOption.Full: + dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemory | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; + break; + case DumpTypeOption.WithHeap: + dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithPrivateReadWriteMemory | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | + NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; + break; + case DumpTypeOption.Mini: + dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo; + break; + } + + // Retry the write dump on ERROR_PARTIAL_COPY + for (int i = 0; i < 5; i++) + { + // Dump the process! + if (NativeMethods.MiniDumpWriteDump(process.Handle, (uint)process.Id, stream.SafeFileHandle, dumpType, ref exceptionInfo, IntPtr.Zero, IntPtr.Zero)) + { + Console.WriteLine("Dumped process."); + return 0; + } + else + { + int err = Marshal.GetHRForLastWin32Error(); + if (err != NativeMethods.ERROR_PARTIAL_COPY) + { + Console.WriteLine($"Error dumping process {err}"); + Marshal.ThrowExceptionForHR(err); + } + else + { + Console.WriteLine($"Error dumping process, was ERROR_PARTIAL_COPY, retrying."); + } + } + } + + Console.WriteLine($"Error dumping process after 5 retries."); + return 1; + } + } + + private static class NativeMethods + { + public const int ERROR_PARTIAL_COPY = unchecked((int)0x8007012b); + + [DllImport("Dbghelp.dll", SetLastError = true)] + public static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeFileHandle hFile, MINIDUMP_TYPE DumpType, ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam); + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct MINIDUMP_EXCEPTION_INFORMATION + { + public uint ThreadId; + public IntPtr ExceptionPointers; + public int ClientPointers; + } + + [Flags] +#pragma warning disable SA1201 // Elements must appear in the correct order + public enum MINIDUMP_TYPE : uint +#pragma warning restore SA1201 // Elements must appear in the correct order + { + MiniDumpNormal = 0, + MiniDumpWithDataSegs = 1 << 0, + MiniDumpWithFullMemory = 1 << 1, + MiniDumpWithHandleData = 1 << 2, + MiniDumpFilterMemory = 1 << 3, + MiniDumpScanMemory = 1 << 4, + MiniDumpWithUnloadedModules = 1 << 5, + MiniDumpWithIndirectlyReferencedMemory = 1 << 6, + MiniDumpFilterModulePaths = 1 << 7, + MiniDumpWithProcessThreadData = 1 << 8, + MiniDumpWithPrivateReadWriteMemory = 1 << 9, + MiniDumpWithoutOptionalData = 1 << 10, + MiniDumpWithFullMemoryInfo = 1 << 11, + MiniDumpWithThreadInfo = 1 << 12, + MiniDumpWithCodeSegs = 1 << 13, + MiniDumpWithoutAuxiliaryState = 1 << 14, + MiniDumpWithFullAuxiliaryState = 1 << 15, + MiniDumpWithPrivateWriteCopyMemory = 1 << 16, + MiniDumpIgnoreInaccessibleMemory = 1 << 17, + MiniDumpWithTokenInformation = 1 << 18, + MiniDumpWithModuleHeaders = 1 << 19, + MiniDumpFilterTriage = 1 << 20, + MiniDumpWithAvxXStateContext = 1 << 21, + MiniDumpWithIptTrace = 1 << 22, + MiniDumpValidTypeFlags = (-1) ^ ((~1) << 22) + } + } + } + + internal enum DumpTypeOption + { + Full, + WithHeap, + Mini, + } + + internal static class DebuggerBreakpoint + { + internal static void WaitForDebugger(string environmentVariable) + { + if (string.IsNullOrWhiteSpace(environmentVariable)) + { + throw new ArgumentException($"'{nameof(environmentVariable)}' cannot be null or whitespace.", nameof(environmentVariable)); + } + + var debugEnabled = Environment.GetEnvironmentVariable(environmentVariable); + if (!string.IsNullOrEmpty(debugEnabled) && debugEnabled.Equals("1", StringComparison.Ordinal)) + { + Console.WriteLine("Waiting for debugger attach..."); + + var currentProcess = Process.GetCurrentProcess(); + Console.WriteLine("Process Id: {0}, Name: {1}", currentProcess.Id, currentProcess.ProcessName); + + while (!Debugger.IsAttached) + { + Thread.Sleep(1000); + } + + Debugger.Break(); + } + } + } +} diff --git a/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj b/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj index 0ac855cdad..2e464bba56 100644 --- a/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj +++ b/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj @@ -7,7 +7,7 @@ Microsoft.VisualStudio.TestPlatform.Client netstandard2.0;net451 - netstandard2.0;net6.0 + net6.0 false diff --git a/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj b/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj index 4b99a6d946..23bcc4fad3 100644 --- a/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj +++ b/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj @@ -7,7 +7,7 @@ Microsoft.VisualStudio.TestPlatform.Common netstandard2.0;netstandard1.3;net451 - netstandard2.0;net6.0 + net6.0 true false diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/Microsoft.TestPlatform.CommunicationUtilities.csproj b/src/Microsoft.TestPlatform.CommunicationUtilities/Microsoft.TestPlatform.CommunicationUtilities.csproj index af0d4e1d08..f3d0faf79e 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/Microsoft.TestPlatform.CommunicationUtilities.csproj +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/Microsoft.TestPlatform.CommunicationUtilities.csproj @@ -6,7 +6,7 @@ Microsoft.TestPlatform.CommunicationUtilities netstandard2.0;netstandard1.3;net451 - netstandard2.0;net6.0 + net6.0 true false true diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Microsoft.TestPlatform.CoreUtilities.csproj b/src/Microsoft.TestPlatform.CoreUtilities/Microsoft.TestPlatform.CoreUtilities.csproj index 292c088187..f1df0c9839 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Microsoft.TestPlatform.CoreUtilities.csproj +++ b/src/Microsoft.TestPlatform.CoreUtilities/Microsoft.TestPlatform.CoreUtilities.csproj @@ -9,7 +9,7 @@ netstandard2.0;netstandard1.3;net451;net45 false $(TargetFrameworks);uap10.0;netstandard1.0 - netstandard2.0;net6.0 + net6.0 false diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj b/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj index 2d715fd706..a05965926c 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj @@ -7,7 +7,7 @@ Microsoft.TestPlatform.CrossPlatEngine netstandard2.0;netstandard1.3;net451 - netstandard2.0;net6.0 + net6.0 true false diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Microsoft.TestPlatform.Extensions.BlameDataCollector.csproj b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Microsoft.TestPlatform.Extensions.BlameDataCollector.csproj index 8b6bd9b02f..754d82898f 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Microsoft.TestPlatform.Extensions.BlameDataCollector.csproj +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Microsoft.TestPlatform.Extensions.BlameDataCollector.csproj @@ -10,7 +10,7 @@ Microsoft.TestPlatform.Extensions.BlameDataCollector netstandard2.0;net472 - netstandard2.0;net6.0 + net6.0 true true false @@ -26,6 +26,8 @@ + + diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs index 4a9a59a66c..90436921f2 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs @@ -19,7 +19,8 @@ public bool Is64Bit(IntPtr processHandle) // WOW64 is the x86 emulator that allows 32 bit Windows - based applications to run seamlessly on 64 bit Windows. // If the function succeeds, the return value is a nonzero value. - if (!IsWow64Process(processHandle, out var isWow64)) + var isWow64Process = IsWow64Process(processHandle, out var isWow64); + if (!isWow64Process) { if (EqtTrace.IsVerboseEnabled) { @@ -27,7 +28,10 @@ public bool Is64Bit(IntPtr processHandle) } } - return !isWow64; + var is64Bit = !isWow64; + EqtTrace.Verbose($"NativeMethodsHelper: is Wow64Process: {isWow64Process} is 64bit: {is64Bit}."); + + return is64Bit; } // A pointer to a value that is set to TRUE if the process is running under WOW64. diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/WindowsHangDumper.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/WindowsHangDumper.cs index 2512bca40d..d06b1e6ed9 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/WindowsHangDumper.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/WindowsHangDumper.cs @@ -8,11 +8,10 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector using System.Globalization; using System.IO; using System.Linq; + using System.Reflection; using System.Runtime.InteropServices; - using System.Threading; using Microsoft.VisualStudio.TestPlatform.ObjectModel; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; - using Microsoft.VisualStudio.TestPlatform.Utilities; + using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.Win32.SafeHandles; internal class WindowsHangDumper : IHangDumper @@ -24,6 +23,20 @@ public WindowsHangDumper(Action logWarning) this.logWarning = logWarning ?? (_ => { }); } + private static Action OutputReceivedCallback => (process, data) => + { + // useful for visibility when debugging this tool + // Console.ForegroundColor = ConsoleColor.Cyan; + // Console.WriteLine(data); + // Console.ForegroundColor = ConsoleColor.White; + // Log all standard output message of procdump in diag files. + // Otherwise they end up coming on console in pipleine. + if (EqtTrace.IsInfoEnabled) + { + EqtTrace.Info("ProcDumpDumper.OutputReceivedCallback: Output received from procdump process: " + data); + } + }; + public void Dump(int processId, string outputDirectory, DumpTypeOption type) { var process = Process.GetProcessById(processId); @@ -102,6 +115,71 @@ internal static void CollectDump(Process process, string outputFile, DumpTypeOpt EqtTrace.Verbose($"WindowsHangDumper.CollectDump: Selected dump type {type}. Dumping {process.Id} - {process.ProcessName} in {outputFile}. "); + if (RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.X86) + { + // This is x86 OS, the current process and the target process must be x86. (Or maybe arm64, but let's not worry about that now). + // Just dump it using PInvoke. + EqtTrace.Verbose($"WindowsHangDumper.CollectDump: We are on x86 Windows, both processes are x86, using PInvoke dumper."); + CollectDumpUsingMiniDumpWriteDump(process, outputFile, type); + } + else if (RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.X64) + { + var targetProcessIs64Bit = new NativeMethodsHelper().Is64Bit(process.Handle); + + var currentProcessIs64Bit = RuntimeInformation.ProcessArchitecture == System.Runtime.InteropServices.Architecture.X64; + + if (targetProcessIs64Bit && currentProcessIs64Bit) + { + // Both processes are x64 architecture, dump it using the PInvoke call. + EqtTrace.Verbose($"WindowsHangDumper.CollectDump: We are on x64 Windows, and both processes are x64, using PInvoke dumper."); + CollectDumpUsingMiniDumpWriteDump(process, outputFile, type); + } + else if (!targetProcessIs64Bit && !currentProcessIs64Bit) + { + // Both processes are x86 architecture, dump it using the PInvoke call. + EqtTrace.Verbose($"WindowsHangDumper.CollectDump: We are on x64 Windows, and both processes are x86, using PInvoke dumper."); + CollectDumpUsingMiniDumpWriteDump(process, outputFile, type); + } + else + { + string dumpMinitoolName; + if (!currentProcessIs64Bit && targetProcessIs64Bit) + { + EqtTrace.Verbose($"WindowsHangDumper.CollectDump: We are on x64 Windows, datacollector is x86, and target process is x64, using 64-bit MiniDumptool."); + dumpMinitoolName = "DumpMinitool.exe"; + } + else + { + EqtTrace.Verbose($"WindowsHangDumper.CollectDump: We are on x64 Windows, datacollector is x64, and target process is x86, using 32-bit MiniDumptool."); + dumpMinitoolName = "DumpMinitool.x86.exe"; + } + + var args = $"--file \"{outputFile}\" --processId {process.Id} --dumpType {type}"; + var dumpMinitoolPath = Path.Combine(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location), dumpMinitoolName); + if (!File.Exists(dumpMinitoolPath)) + { + throw new FileNotFoundException("Could not find DumpMinitool", dumpMinitoolPath); + } + + EqtTrace.Info($"ProcDumpDumper.CollectDump: Running DumpMinitool: '{dumpMinitoolPath} {args}'."); + var dumpMiniTool = new ProcessHelper().LaunchProcess( + dumpMinitoolPath, + args, + Path.GetDirectoryName(outputFile), + null, + null, + null, + OutputReceivedCallback) as Process; + dumpMiniTool.WaitForExit(); + EqtTrace.Info($"ProcDumpDumper.CollectDump: {dumpMinitoolName} exited with exitcode: '{dumpMiniTool.ExitCode}'."); + } + } + + EqtTrace.Verbose($"WindowsHangDumper.CollectDump: Finished dumping {process.Id} - {process.ProcessName} in {outputFile}. "); + } + + private static void CollectDumpUsingMiniDumpWriteDump(Process process, string outputFile, DumpTypeOption type) + { // Open the file for writing using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { @@ -151,8 +229,6 @@ internal static void CollectDump(Process process, string outputFile, DumpTypeOpt } } } - - EqtTrace.Verbose($"WindowsHangDumper.CollectDump: Finished dumping {process.Id} - {process.ProcessName} in {outputFile}. "); } private static class NativeMethods diff --git a/src/Microsoft.TestPlatform.Extensions.HtmlLogger/Microsoft.TestPlatform.Extensions.HtmlLogger.csproj b/src/Microsoft.TestPlatform.Extensions.HtmlLogger/Microsoft.TestPlatform.Extensions.HtmlLogger.csproj index 249ff5570e..564d119eb3 100644 --- a/src/Microsoft.TestPlatform.Extensions.HtmlLogger/Microsoft.TestPlatform.Extensions.HtmlLogger.csproj +++ b/src/Microsoft.TestPlatform.Extensions.HtmlLogger/Microsoft.TestPlatform.Extensions.HtmlLogger.csproj @@ -8,7 +8,7 @@ Microsoft.VisualStudio.TestPlatform.Extensions.Html.TestLogger true netstandard2.0;net451 - netstandard2.0;net6.0 + net6.0 false diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj index 95348de4c4..a370d444f5 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj @@ -8,7 +8,7 @@ Microsoft.VisualStudio.TestPlatform.Extensions.Trx.TestLogger true netstandard2.0;net451 - netstandard2.0;net6.0 + net6.0 false diff --git a/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj b/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj index 0a519bfae6..451c871c83 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj +++ b/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj @@ -8,7 +8,7 @@ Microsoft.VisualStudio.TestPlatform.ObjectModel net45;net451;netcoreapp2.1;netcoreapp1.0;netstandard2.0;netstandard1.3 $(TargetFrameworks);uap10.0;netstandard1.0 - netstandard2.0;net6.0 + net6.0 Microsoft.TestPlatform.ObjectModel false diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj index b7a59cb394..2d4f07e3f3 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj @@ -10,7 +10,7 @@ Microsoft.TestPlatform.PlatformAbstractions net45;net451;netcoreapp1.0;netcoreapp2.1;netstandard1.3;netstandard2.0 $(TargetFrameworks);uap10.0;netstandard1.0 - netstandard2.0;net6.0 + net6.0 true false diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj b/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj index a12114d680..6af482f19c 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj +++ b/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj @@ -7,7 +7,7 @@ Microsoft.TestPlatform.TestHostRuntimeProvider netstandard2.0;net451 - netstandard2.0;net6.0 + net6.0 $(DefineConstants);DOTNET_BUILD_FROM_SOURCE true false diff --git a/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj b/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj index 358a76f666..5ca7b108d1 100644 --- a/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj +++ b/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj @@ -7,7 +7,7 @@ Microsoft.TestPlatform.Utilities netstandard2.0;netstandard1.3;net451 - netstandard2.0;net6.0 + net6.0 false diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj index 9af1703496..70ced3649b 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj @@ -7,7 +7,7 @@ Microsoft.TestPlatform.VsTestConsole.TranslationLayer netstandard2.0;net451 - netstandard2.0;net6.0 + net6.0 true false diff --git a/src/SettingsMigrator/SettingsMigrator.csproj b/src/SettingsMigrator/SettingsMigrator.csproj index d9d37e5c3a..f1a3b92d9e 100644 --- a/src/SettingsMigrator/SettingsMigrator.csproj +++ b/src/SettingsMigrator/SettingsMigrator.csproj @@ -7,7 +7,7 @@ SettingsMigrator net451 - netstandard2.0;net6.0 + net6.0 true true Exe diff --git a/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec b/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec index d7a6130aaf..c9db7ca2b4 100644 --- a/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec +++ b/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec @@ -131,6 +131,10 @@ + + + + @@ -366,6 +370,10 @@ + + + + diff --git a/src/package/nuspec/Microsoft.TestPlatform.nuspec b/src/package/nuspec/Microsoft.TestPlatform.nuspec index e001d5a950..52891a9a68 100644 --- a/src/package/nuspec/Microsoft.TestPlatform.nuspec +++ b/src/package/nuspec/Microsoft.TestPlatform.nuspec @@ -223,9 +223,13 @@ - + + + + + - + diff --git a/src/package/sign/sign.proj b/src/package/sign/sign.proj index 6d43420713..8c6514a604 100644 --- a/src/package/sign/sign.proj +++ b/src/package/sign/sign.proj @@ -90,7 +90,9 @@ - + + + @@ -364,6 +366,8 @@ + + diff --git a/src/vstest.console/vstest.console.csproj b/src/vstest.console/vstest.console.csproj index 1343e6d904..7c55559126 100644 --- a/src/vstest.console/vstest.console.csproj +++ b/src/vstest.console/vstest.console.csproj @@ -8,7 +8,7 @@ vstest.console netcoreapp2.1;net451 - netcoreapp2.1;net6.0 + net6.0 true Exe false