From 3f228abc9257bbc21ea4fb87463835432edbf338 Mon Sep 17 00:00:00 2001 From: Vagisha Nidhi Date: Thu, 26 Jul 2018 17:30:18 +0530 Subject: [PATCH 1/3] ProcDump Args Changed --- .../Constants.cs | 5 ++ .../ProcessDumpUtility.cs | 28 ++++--- .../ProcessDumpUtilityTests.cs | 80 +++++++++++++++---- 3 files changed, 87 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs index f060ab8a0a..0739a1d2c9 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs @@ -42,5 +42,10 @@ internal static class Constants /// Configuration key name for dump mode /// public const string DumpModeKey = "CollectDump"; + + /// + /// X86 Test Host Process Name + /// + public const string X86TestHostProcessName = "testhost.x86"; } } diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs index 34388a84b1..28029df7d9 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs @@ -5,7 +5,6 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector { using System; using System.Diagnostics; - using System.Globalization; using System.IO; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; @@ -77,7 +76,7 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu this.testResultsDirectory = testResultsDirectory; this.procDumpProcess = this.processHelper.LaunchProcess( - this.GetProcDumpExecutable(), + this.GetProcDumpExecutable(processId), ProcessDumpUtility.BuildProcDumpArgs(processId, this.dumpFileName), testResultsDirectory, null, @@ -100,27 +99,38 @@ private static string BuildProcDumpArgs(int processId, string filename) // -accepteula: Auto accept end-user license agreement // -t: Write a dump when the process terminates. // This will create a minidump of the process with specified filename - return "-accepteula -t " + processId + " " + filename + ".dmp"; + return "-accepteula -e 1 -g -t -f STACK_OVERFLOW -f ACCESS_VIOLATION " + processId + " " + filename + ".dmp"; } /// /// Get procdump executable path /// + /// + /// Process Id + /// /// procdump executable path - private string GetProcDumpExecutable() + private string GetProcDumpExecutable(int processId) { var procdumpPath = Environment.GetEnvironmentVariable("PROCDUMP_PATH"); + string processName = this.processHelper.GetProcessName(processId); + + if (EqtTrace.IsVerboseEnabled) + { + EqtTrace.Verbose("Using process name {0}", processName); + } + if (!string.IsNullOrWhiteSpace(procdumpPath)) { string filename = string.Empty; - if (this.environment.Architecture == PlatformArchitecture.X64) + // Launch procdump according to process architecture + if (this.environment.Architecture == PlatformArchitecture.X86 || processName == Constants.X86TestHostProcessName) { - filename = "procdump64.exe"; + filename = "procdump.exe"; } - else if (this.environment.Architecture == PlatformArchitecture.X86) + else if (this.environment.Architecture == PlatformArchitecture.X64) { - filename = "procdump.exe"; + filename = "procdump64.exe"; } var procDumpExe = Path.Combine(procdumpPath, filename); @@ -138,4 +148,4 @@ private string GetProcDumpExecutable() } } } -} +} \ No newline at end of file diff --git a/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs b/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs index 57fa1d51fe..d26912efc2 100644 --- a/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs @@ -47,14 +47,20 @@ public ProcessDumpUtilityTests() [TestMethod] public void GetDumpFileWillThrowExceptionIfNoDumpfile() { + var guid = "guid"; + var process = "process"; + var processId = 12345; + var testResultsDirectory = "D:\\TestResults"; + this.mockFileHelper.Setup(x => x.GetFiles(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new string[] { }); - + this.mockProcessHelper.Setup(x => x.GetProcessName(processId)) + .Returns(process); this.mockProcessHelper.Setup(x => x.LaunchProcess(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) .Returns(this.mockProcDumpProcess.Object); var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); - processDumpUtility.StartProcessDump(12345, "guid", "D:\\TestResults"); + processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); var ex = Assert.ThrowsException(() => processDumpUtility.GetDumpFile()); Assert.AreEqual(ex.Message, Resources.Resources.DumpFileNotGeneratedErrorMessage); @@ -66,12 +72,19 @@ public void GetDumpFileWillThrowExceptionIfNoDumpfile() [TestMethod] public void GetDumpFileWillReturnEmptyIfProcDumpDidntStart() { + var guid = "guid"; + var process = "process"; + var processId = 12345; + var testResultsDirectory = "D:\\TestResults"; + this.mockProcessHelper.Setup(x => x.LaunchProcess(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) .Throws(new Exception()); + this.mockProcessHelper.Setup(x => x.GetProcessName(processId)) + .Returns(process); var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); - Assert.ThrowsException(() => processDumpUtility.StartProcessDump(12345, "guid", "D:\\TestResults")); + Assert.ThrowsException(() => processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory)); Assert.AreEqual(string.Empty, processDumpUtility.GetDumpFile()); } @@ -81,15 +94,21 @@ public void GetDumpFileWillReturnEmptyIfProcDumpDidntStart() [TestMethod] public void GetDumpFileWillWaitForProcessToExitAndGetDumpFile() { + var guid = "guid"; + var process = "process"; + var processId = 12345; + var testResultsDirectory = "D:\\TestResults"; + this.mockFileHelper.Setup(x => x.GetFiles(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new string[] { "dump.dmp" }); - + this.mockProcessHelper.Setup(x => x.GetProcessName(processId)) + .Returns(process); this.mockProcessHelper.Setup(x => x.LaunchProcess(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) .Returns(this.mockProcDumpProcess.Object); var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); - processDumpUtility.StartProcessDump(12345, "guid", "D:\\TestResults"); + processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); processDumpUtility.GetDumpFile(); this.mockProcessHelper.Verify(x => x.WaitForProcessExit(It.IsAny()), Times.Once); @@ -105,7 +124,7 @@ public void StartProcessDumpWillStartProcDumpExeWithCorrectParamsAndGetDumpFileR var process = "process"; var processId = 12345; var filename = $"{process}_{processId}_{guid}.dmp"; - var args = $"-accepteula -t {processId} {filename}"; + var args = $"-accepteula -e 1 -g -t -f STACK_OVERFLOW -f ACCESS_VIOLATION {processId} {filename}"; var testResultsDirectory = "D:\\TestResults"; this.mockProcessHelper.Setup(x => x.LaunchProcess(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) @@ -138,27 +157,54 @@ public void StartProcessDumpWillThrowErrorIfProcdumpEnvVarNotSet() } /// - /// Start process dump will start exe corresponding to platform architecture + /// Start process dump will start exe according to Test host Process /// [TestMethod] - public void StartProcessDumpWillStartExeCorrespondingToPlatformArchitecture() + public void StartProcessDumpWillStartExeCorrespondingToTestHostProcessIn32BitOS() { - PlatformArchitecture[] platformArchitecture = { PlatformArchitecture.X64, PlatformArchitecture.X86 }; + var guid = "guid"; + var process = "process"; + var processId = 12345; + var testResultsDirectory = "D:\\TestResults"; + + this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X86); + this.mockProcessHelper.Setup(x => x.GetProcessName(processId)) + .Returns(process); + var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + + processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); + + this.mockProcessHelper.Verify(x => x.LaunchProcess(Path.Combine("D:\\procdump", "procdump.exe"), It.IsAny(), It.IsAny(), null, null, null)); + } - Dictionary architectureExeMap = new Dictionary() + /// + /// Start process dump will start exe according to Test host Process + /// + [TestMethod] + public void StartProcessDumpWillStartExeCorrespondingToTestHostProcessIn64BitOS() + { + Dictionary processIdNameMap = new Dictionary() { - { PlatformArchitecture.X86, "procdump.exe" }, - { PlatformArchitecture.X64, "procdump64.exe" } + { 1234, "testhost.x86" }, + { 12345, "testhost" } }; - foreach (var architecture in architectureExeMap) + Dictionary processExeMap = new Dictionary() { - this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(architecture.Key); + { "testhost.x86", "procdump.exe" }, + { "testhost", "procdump64.exe" } + }; + this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X64); + + foreach (var process in processIdNameMap) + { + this.mockProcessHelper.Setup(x => x.GetProcessName(process.Key)) + .Returns(process.Value); var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); - processDumpUtility.StartProcessDump(1234, "guid", "D:\\"); + processDumpUtility.StartProcessDump(process.Key, "guid", "D:\\"); - this.mockProcessHelper.Verify(x => x.LaunchProcess(Path.Combine("D:\\procdump", architecture.Value), It.IsAny(), It.IsAny(), null, null, null)); + this.mockProcessHelper.Verify(x => x.LaunchProcess(Path.Combine("D:\\procdump", processExeMap[process.Value]), It.IsAny(), It.IsAny(), null, null, null)); } } @@ -168,4 +214,4 @@ public void TestCleanup() Environment.SetEnvironmentVariable("PROCDUMP_PATH", null); } } -} +} \ No newline at end of file From 3ced4752ca9e88017e6fddfb7881762921ebdf32 Mon Sep 17 00:00:00 2001 From: Vagisha Nidhi Date: Tue, 31 Jul 2018 10:17:42 +0530 Subject: [PATCH 2/3] Iswow64 used for 32bit process --- .../Constants.cs | 9 +- .../Interfaces/INativeMethodsHelper.cs | 17 +++ .../NativeMethodsHelper.cs | 34 +++++ .../ProcessDumpUtility.cs | 55 ++++--- .../Interfaces/System/IProcessHelper.cs | 7 + .../net451/System/ProcessHelper.cs | 7 + .../netcore/System/ProcessHelper.cs | 7 + .../netstandard1.0/System/ProcessHelper.cs | 6 +- .../uap10.0/System/ProcessHelper.cs | 7 +- .../ProcessDumpUtilityTests.cs | 134 +++++++++++++++--- 10 files changed, 246 insertions(+), 37 deletions(-) create mode 100644 src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Interfaces/INativeMethodsHelper.cs create mode 100644 src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs index 0739a1d2c9..b1bd1b9464 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs @@ -44,8 +44,13 @@ internal static class Constants public const string DumpModeKey = "CollectDump"; /// - /// X86 Test Host Process Name + /// Procdump 32 bit version /// - public const string X86TestHostProcessName = "testhost.x86"; + public const string ProcdumpProcessName = "procdump.exe"; + + /// + /// Procdump 64 bit version + /// + public const string Procdump64ProcessName = "procdump64.exe"; } } diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Interfaces/INativeMethodsHelper.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Interfaces/INativeMethodsHelper.cs new file mode 100644 index 0000000000..6a6173540e --- /dev/null +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Interfaces/INativeMethodsHelper.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces +{ + using System; + + public interface INativeMethodsHelper + { + /// + /// Returns if a process is 64 bit process + /// + /// Process Handle + /// Bool for Is64Bit + bool Is64Bit(IntPtr processHandle); + } +} diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs new file mode 100644 index 0000000000..6ad1f61c1b --- /dev/null +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.TestPlatform.Extensions.BlameDataCollector +{ + using System; + using System.ComponentModel; + using System.Runtime.InteropServices; + using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces; + + public class NativeMethodsHelper : INativeMethodsHelper + { + /// + /// Returns if a process is 64 bit process + /// + /// Process Handle + /// Bool for Is64Bit + public bool Is64Bit(IntPtr processHandle) + { + // WOW64 is the x86 emulator that allows 32 bit Windows - based applications to run seamlessly on 64 bit Windows. + bool isWow64 = false; + if (!IsWow64Process(processHandle, out isWow64)) + { + throw new Win32Exception(); + } + + return !isWow64; + } + + [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process); + } +} diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs index 28029df7d9..c90b781ca4 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs @@ -4,8 +4,11 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector { using System; + using System.Collections.Generic; using System.Diagnostics; using System.IO; + using System.Text; + using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; @@ -14,27 +17,30 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector public class ProcessDumpUtility : IProcessDumpUtility { + private static List procDumpExceptionsList; private IProcessHelper processHelper; private IFileHelper fileHelper; private IEnvironment environment; private Process procDumpProcess; private string testResultsDirectory; private string dumpFileName; + private INativeMethodsHelper nativeMethodsHelper; public ProcessDumpUtility() - : this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment()) + : this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment(), new NativeMethodsHelper()) { } - public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment) + public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment, INativeMethodsHelper nativeMethodsHelper) { this.processHelper = processHelper; this.fileHelper = fileHelper; this.environment = environment; + this.nativeMethodsHelper = nativeMethodsHelper; } - /// - public string GetDumpFile() + /// + public string GetDumpFile() { if (this.procDumpProcess == null) { @@ -96,10 +102,26 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu /// Arguments private static string BuildProcDumpArgs(int processId, string filename) { + ProcessDumpUtility.procDumpExceptionsList = new List() + { + "STACK_OVERFLOW", + "ACCESS_VIOLATION" + }; + // -accepteula: Auto accept end-user license agreement + // -e: Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions. + // -g: Run as a native debugger in a managed process (no interop). // -t: Write a dump when the process terminates. - // This will create a minidump of the process with specified filename - return "-accepteula -e 1 -g -t -f STACK_OVERFLOW -f ACCESS_VIOLATION " + processId + " " + filename + ".dmp"; + // -f: Filter the exceptions. + // This will create a minidump of the process with specified filename. + StringBuilder procDumpArgument = new StringBuilder("-accepteula -e 1 -g -t "); + foreach (var exceptionFilter in ProcessDumpUtility.procDumpExceptionsList) + { + procDumpArgument.Append($"-f {exceptionFilter} "); + } + + procDumpArgument.Append($"{processId} {filename}.dmp"); + return procDumpArgument.ToString(); } /// @@ -112,25 +134,26 @@ private static string BuildProcDumpArgs(int processId, string filename) private string GetProcDumpExecutable(int processId) { var procdumpPath = Environment.GetEnvironmentVariable("PROCDUMP_PATH"); - string processName = this.processHelper.GetProcessName(processId); - - if (EqtTrace.IsVerboseEnabled) - { - EqtTrace.Verbose("Using process name {0}", processName); - } if (!string.IsNullOrWhiteSpace(procdumpPath)) { string filename = string.Empty; // Launch procdump according to process architecture - if (this.environment.Architecture == PlatformArchitecture.X86 || processName == Constants.X86TestHostProcessName) + if (this.environment.Architecture == PlatformArchitecture.X86) { - filename = "procdump.exe"; + filename = Constants.ProcdumpProcessName; } - else if (this.environment.Architecture == PlatformArchitecture.X64) + else { - filename = "procdump64.exe"; + if (this.nativeMethodsHelper.Is64Bit(this.processHelper.GetProcessHandleById(processId))) + { + filename = Constants.Procdump64ProcessName; + } + else + { + filename = Constants.ProcdumpProcessName; + } } var procDumpExe = Path.Combine(procdumpPath, filename); diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs index 28f11daf95..2af67bf84f 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs @@ -103,5 +103,12 @@ public interface IProcessHelper /// /// Reference to process void WaitForProcessExit(object process); + + /// + /// Gets the process handle for given process Id. + /// + /// process id + /// Process Handle + IntPtr GetProcessHandleById(int processId); } } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs index 7facdab6ad..c00bc77394 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs @@ -3,6 +3,8 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions { + using System; + using System.Diagnostics; using System.IO; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; @@ -13,5 +15,10 @@ public string GetCurrentProcessLocation() { return Path.GetDirectoryName(this.GetCurrentProcessFileName()); } + + public IntPtr GetProcessHandleById(int processId) + { + return Process.GetProcessById(processId).Handle; + } } } \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs index 530da3bce4..0ea13186ef 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs @@ -3,6 +3,8 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions { + using System; + using System.Diagnostics; using System.IO; using System.Reflection; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; @@ -14,5 +16,10 @@ public string GetCurrentProcessLocation() { return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); } + + public IntPtr GetProcessHandleById(int processId) + { + return Process.GetProcessById(processId).SafeHandle.DangerousGetHandle(); + } } } \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs index 1b9b91dcd2..71a7e03d0e 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs @@ -5,7 +5,6 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions { using System; using System.Collections.Generic; - using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; /// @@ -96,5 +95,10 @@ public void WaitForProcessExit(object process) { throw new NotImplementedException(); } + + public IntPtr GetProcessHandleById(int processId) + { + throw new NotImplementedException(); + } } } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs index d25affc257..3bb3bc76f7 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs @@ -11,7 +11,7 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions /// /// Helper class to deal with process related functionality. /// - public class ProcessHelper : IProcessHelper + public partial class ProcessHelper : IProcessHelper { /// public object LaunchProcess( @@ -101,5 +101,10 @@ public void WaitForProcessExit(object process) { throw new NotImplementedException(); } + + public IntPtr GetProcessHandleById(int processId) + { + throw new NotImplementedException(); + } } } diff --git a/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs b/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs index d26912efc2..cc5d9b16d6 100644 --- a/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs @@ -9,6 +9,7 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests using System.IO; using Microsoft.TestPlatform.Extensions.BlameDataCollector; + using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; @@ -27,6 +28,7 @@ public class ProcessDumpUtilityTests private Mock mockProcessHelper; private Mock mockProcDumpProcess; private Mock mockPlatformEnvironment; + private Mock mockNativeMethodsHelper; /// /// Initializes a new instance of the class. @@ -37,6 +39,7 @@ public ProcessDumpUtilityTests() this.mockProcessHelper = new Mock(); this.mockProcDumpProcess = new Mock(); this.mockPlatformEnvironment = new Mock(); + this.mockNativeMethodsHelper = new Mock(); Environment.SetEnvironmentVariable("PROCDUMP_PATH", "D:\\procdump"); } @@ -59,7 +62,12 @@ public void GetDumpFileWillThrowExceptionIfNoDumpfile() this.mockProcessHelper.Setup(x => x.LaunchProcess(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) .Returns(this.mockProcDumpProcess.Object); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); + processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); var ex = Assert.ThrowsException(() => processDumpUtility.GetDumpFile()); @@ -82,7 +90,11 @@ public void GetDumpFileWillReturnEmptyIfProcDumpDidntStart() this.mockProcessHelper.Setup(x => x.GetProcessName(processId)) .Returns(process); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); Assert.ThrowsException(() => processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory)); Assert.AreEqual(string.Empty, processDumpUtility.GetDumpFile()); @@ -106,7 +118,11 @@ public void GetDumpFileWillWaitForProcessToExitAndGetDumpFile() this.mockProcessHelper.Setup(x => x.LaunchProcess(It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) .Returns(this.mockProcDumpProcess.Object); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); processDumpUtility.GetDumpFile(); @@ -135,7 +151,12 @@ public void StartProcessDumpWillStartProcDumpExeWithCorrectParamsAndGetDumpFileR this.mockFileHelper.Setup(x => x.GetFiles(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new string[] { Path.Combine(testResultsDirectory, filename) }); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); + processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); this.mockProcessHelper.Verify(x => x.LaunchProcess(It.IsAny(), args, It.IsAny(), null, null, null), Times.Once); @@ -150,7 +171,11 @@ public void StartProcessDumpWillThrowErrorIfProcdumpEnvVarNotSet() { Environment.SetEnvironmentVariable("PROCDUMP_PATH", null); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); var ex = Assert.ThrowsException(() => processDumpUtility.StartProcessDump(1234, "guid", "D:\\")); Assert.AreEqual(ex.Message, Resources.Resources.ProcDumpEnvVarEmpty); @@ -163,14 +188,20 @@ public void StartProcessDumpWillThrowErrorIfProcdumpEnvVarNotSet() public void StartProcessDumpWillStartExeCorrespondingToTestHostProcessIn32BitOS() { var guid = "guid"; - var process = "process"; + + // var process = "process"; var processId = 12345; var testResultsDirectory = "D:\\TestResults"; this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X86); - this.mockProcessHelper.Setup(x => x.GetProcessName(processId)) - .Returns(process); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + this.mockProcessHelper.Setup(x => x.GetProcessHandleById(processId)) + .Returns(new IntPtr(0)); + + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); processDumpUtility.StartProcessDump(processId, guid, testResultsDirectory); @@ -183,31 +214,100 @@ public void StartProcessDumpWillStartExeCorrespondingToTestHostProcessIn32BitOS( [TestMethod] public void StartProcessDumpWillStartExeCorrespondingToTestHostProcessIn64BitOS() { - Dictionary processIdNameMap = new Dictionary() + IntPtr x86Ptr = new IntPtr(0); + IntPtr x64Ptr = new IntPtr(1); + + Dictionary processIdNameMap = new Dictionary() + { + { 1234, x86Ptr }, + { 12345, x64Ptr } + }; + + Dictionary iS64BitMap = new Dictionary() { - { 1234, "testhost.x86" }, - { 12345, "testhost" } + { x86Ptr, false }, + { x64Ptr, true } }; - Dictionary processExeMap = new Dictionary() + Dictionary processExeMap = new Dictionary() { - { "testhost.x86", "procdump.exe" }, - { "testhost", "procdump64.exe" } + { x86Ptr, "procdump.exe" }, + { x64Ptr, "procdump64.exe" } }; this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X64); foreach (var process in processIdNameMap) { - this.mockProcessHelper.Setup(x => x.GetProcessName(process.Key)) + this.mockProcessHelper.Setup(x => x.GetProcessHandleById(process.Key)) .Returns(process.Value); - var processDumpUtility = new ProcessDumpUtility(this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockPlatformEnvironment.Object); + this.mockNativeMethodsHelper.Setup(x => x.Is64Bit(process.Value)) + .Returns(iS64BitMap[process.Value]); + + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); + processDumpUtility.StartProcessDump(process.Key, "guid", "D:\\"); this.mockProcessHelper.Verify(x => x.LaunchProcess(Path.Combine("D:\\procdump", processExeMap[process.Value]), It.IsAny(), It.IsAny(), null, null, null)); } } + /// + /// Start process dump will start exe according to Test host Process + /// + [TestMethod] + public void StartProcessDumpWillStartExeCorrespondingTo64BitTestHostProcessIn64BitOS() + { + IntPtr x64ProcessHandle = new IntPtr(0); + int processId = 1234; + this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X64); + + this.mockProcessHelper.Setup(x => x.GetProcessHandleById(processId)) + .Returns(x64ProcessHandle); + this.mockNativeMethodsHelper.Setup(x => x.Is64Bit(x64ProcessHandle)) + .Returns(true); + + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); + + processDumpUtility.StartProcessDump(processId, "guid", "D:\\"); + + this.mockProcessHelper.Verify(x => x.LaunchProcess(Path.Combine("D:\\procdump", "procdump64.exe"), It.IsAny(), It.IsAny(), null, null, null)); + } + + /// + /// Start process dump will start exe according to Test host Process + /// + [TestMethod] + public void StartProcessDumpWillStartExeCorrespondingTo32BitTestHostProcessIn64BitOS() + { + IntPtr x86ProcessHandle = new IntPtr(0); + int processId = 12345; + this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X64); + + this.mockProcessHelper.Setup(x => x.GetProcessHandleById(processId)) + .Returns(x86ProcessHandle); + this.mockNativeMethodsHelper.Setup(x => x.Is64Bit(x86ProcessHandle)) + .Returns(false); + + var processDumpUtility = new ProcessDumpUtility( + this.mockProcessHelper.Object, + this.mockFileHelper.Object, + this.mockPlatformEnvironment.Object, + this.mockNativeMethodsHelper.Object); + + processDumpUtility.StartProcessDump(processId, "guid", "D:\\"); + + this.mockProcessHelper.Verify(x => x.LaunchProcess(Path.Combine("D:\\procdump", "procdump.exe"), It.IsAny(), It.IsAny(), null, null, null)); + } + [TestCleanup] public void TestCleanup() { From 65a32632c0abab5bac0fbfcbd4582508ca8d4feb Mon Sep 17 00:00:00 2001 From: Vagisha Nidhi Date: Wed, 1 Aug 2018 14:09:27 +0530 Subject: [PATCH 3/3] Minor fixes --- .../Constants.cs | 4 +-- .../NativeMethodsHelper.cs | 12 +++++-- .../ProcessDumpUtility.cs | 32 +++++++++---------- .../Interfaces/System/IProcessHelper.cs | 2 +- .../net451/System/ProcessHelper.cs | 2 +- .../netcore/System/ProcessHelper.cs | 5 ++- .../netstandard1.0/System/ProcessHelper.cs | 2 +- .../uap10.0/System/ProcessHelper.cs | 2 +- .../ProcessDumpUtilityTests.cs | 6 ++-- 9 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs index 08580a33a1..b5ecb404c3 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs @@ -46,12 +46,12 @@ internal static class Constants /// /// Procdump 32 bit version /// - public const string ProcdumpProcessName = "procdump.exe"; + public const string ProcdumpProcess = "procdump.exe"; /// /// Procdump 64 bit version /// - public const string Procdump64ProcessName = "procdump64.exe"; + public const string Procdump64Process = "procdump64.exe"; /// /// Configuration key name for collect dump always diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs index 6ad1f61c1b..52f2b2bf5e 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/NativeMethodsHelper.cs @@ -4,9 +4,9 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector { using System; - using System.ComponentModel; using System.Runtime.InteropServices; using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; public class NativeMethodsHelper : INativeMethodsHelper { @@ -19,14 +19,22 @@ public bool Is64Bit(IntPtr processHandle) { // WOW64 is the x86 emulator that allows 32 bit Windows - based applications to run seamlessly on 64 bit Windows. bool isWow64 = false; + + // If the function succeeds, the return value is a nonzero value. if (!IsWow64Process(processHandle, out isWow64)) { - throw new Win32Exception(); + if (EqtTrace.IsVerboseEnabled) + { + EqtTrace.Verbose("NativeMethodsHelper: The call to IsWow64Process failed."); + } } return !isWow64; } + // 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. + // If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process); diff --git a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs index 233ce116e0..8fd3d88356 100644 --- a/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs +++ b/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs @@ -37,6 +37,11 @@ public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, this.fileHelper = fileHelper; this.environment = environment; this.nativeMethodsHelper = nativeMethodsHelper; + ProcessDumpUtility.procDumpExceptionsList = new List() + { + "STACK_OVERFLOW", + "ACCESS_VIOLATION" + }; } /// @@ -105,12 +110,6 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu /// Arguments private static string BuildProcDumpArgs(int processId, string filename, bool isFullDump = false) { - ProcessDumpUtility.procDumpExceptionsList = new List() - { - "STACK_OVERFLOW", - "ACCESS_VIOLATION" - }; - // -accepteula: Auto accept end-user license agreement // -e: Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions. // -g: Run as a native debugger in a managed process (no interop). @@ -129,7 +128,14 @@ private static string BuildProcDumpArgs(int processId, string filename, bool isF } procDumpArgument.Append($"{processId} {filename}.dmp"); - return procDumpArgument.ToString(); + var argument = procDumpArgument.ToString(); + + if (EqtTrace.IsInfoEnabled) + { + EqtTrace.Info($"ProcessDumpUtility : The procdump argument is {argument}"); + } + + return argument; } /// @@ -150,18 +156,12 @@ private string GetProcDumpExecutable(int processId) // Launch procdump according to process architecture if (this.environment.Architecture == PlatformArchitecture.X86) { - filename = Constants.ProcdumpProcessName; + filename = Constants.ProcdumpProcess; } else { - if (this.nativeMethodsHelper.Is64Bit(this.processHelper.GetProcessHandleById(processId))) - { - filename = Constants.Procdump64ProcessName; - } - else - { - filename = Constants.ProcdumpProcessName; - } + filename = this.nativeMethodsHelper.Is64Bit(this.processHelper.GetProcessHandle(processId)) ? + Constants.Procdump64Process : Constants.ProcdumpProcess; } var procDumpExe = Path.Combine(procdumpPath, filename); diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs index 2af67bf84f..3050ea0f1b 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs @@ -109,6 +109,6 @@ public interface IProcessHelper /// /// process id /// Process Handle - IntPtr GetProcessHandleById(int processId); + IntPtr GetProcessHandle(int processId); } } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs index c00bc77394..6e637d0e03 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs @@ -16,7 +16,7 @@ public string GetCurrentProcessLocation() return Path.GetDirectoryName(this.GetCurrentProcessFileName()); } - public IntPtr GetProcessHandleById(int processId) + public IntPtr GetProcessHandle(int processId) { return Process.GetProcessById(processId).Handle; } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs index 0ea13186ef..793671e6e8 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs @@ -17,8 +17,11 @@ public string GetCurrentProcessLocation() return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); } - public IntPtr GetProcessHandleById(int processId) + /// + public IntPtr GetProcessHandle(int processId) { + // An IntPtr representing the value of the handle field. + // If the handle has been marked invalid with SetHandleAsInvalid, this method still returns the original handle value, which can be a stale value. return Process.GetProcessById(processId).SafeHandle.DangerousGetHandle(); } } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs index 71a7e03d0e..7f1142eb3d 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs @@ -96,7 +96,7 @@ public void WaitForProcessExit(object process) throw new NotImplementedException(); } - public IntPtr GetProcessHandleById(int processId) + public IntPtr GetProcessHandle(int processId) { throw new NotImplementedException(); } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs index 3bb3bc76f7..87f14b6c5f 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs @@ -102,7 +102,7 @@ public void WaitForProcessExit(object process) throw new NotImplementedException(); } - public IntPtr GetProcessHandleById(int processId) + public IntPtr GetProcessHandle(int processId) { throw new NotImplementedException(); } diff --git a/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs b/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs index 1b0d0efdad..17a8277a62 100644 --- a/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests/ProcessDumpUtilityTests.cs @@ -226,7 +226,7 @@ public void StartProcessDumpWillStartExeCorrespondingToTestHostProcessIn32BitOS( var testResultsDirectory = "D:\\TestResults"; this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X86); - this.mockProcessHelper.Setup(x => x.GetProcessHandleById(processId)) + this.mockProcessHelper.Setup(x => x.GetProcessHandle(processId)) .Returns(new IntPtr(0)); var processDumpUtility = new ProcessDumpUtility( @@ -250,7 +250,7 @@ public void StartProcessDumpWillStartExeCorrespondingTo64BitTestHostProcessIn64B int processId = 1234; this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X64); - this.mockProcessHelper.Setup(x => x.GetProcessHandleById(processId)) + this.mockProcessHelper.Setup(x => x.GetProcessHandle(processId)) .Returns(x64ProcessHandle); this.mockNativeMethodsHelper.Setup(x => x.Is64Bit(x64ProcessHandle)) .Returns(true); @@ -276,7 +276,7 @@ public void StartProcessDumpWillStartExeCorrespondingTo32BitTestHostProcessIn64B int processId = 12345; this.mockPlatformEnvironment.Setup(x => x.Architecture).Returns(PlatformArchitecture.X64); - this.mockProcessHelper.Setup(x => x.GetProcessHandleById(processId)) + this.mockProcessHelper.Setup(x => x.GetProcessHandle(processId)) .Returns(x86ProcessHandle); this.mockNativeMethodsHelper.Setup(x => x.Is64Bit(x86ProcessHandle)) .Returns(false);