Skip to content

Commit 3db5c0d

Browse files
Procdump Arguments Changed (microsoft#1700)
* ProcDump Args Changed * Iswow64 used for 32bit process * Minor fixes
1 parent 4e205d0 commit 3db5c0d

File tree

10 files changed

+283
-49
lines changed

10 files changed

+283
-49
lines changed

src/Microsoft.TestPlatform.Extensions.BlameDataCollector/Constants.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ internal static class Constants
4444
public const string DumpModeKey = "CollectDump";
4545

4646
/// <summary>
47+
/// Procdump 32 bit version
48+
/// </summary>
49+
public const string ProcdumpProcess = "procdump.exe";
50+
51+
/// <summary>
52+
/// Procdump 64 bit version
53+
/// </summary>
54+
public const string Procdump64Process = "procdump64.exe";
55+
56+
///<summary>
4757
/// Configuration key name for collect dump always
4858
/// </summary>
4959
public const string CollectDumpAlwaysKey = "CollectAlways";
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces
5+
{
6+
using System;
7+
8+
public interface INativeMethodsHelper
9+
{
10+
/// <summary>
11+
/// Returns if a process is 64 bit process
12+
/// </summary>
13+
/// <param name="processHandle">Process Handle</param>
14+
/// <returns>Bool for Is64Bit</returns>
15+
bool Is64Bit(IntPtr processHandle);
16+
}
17+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector
5+
{
6+
using System;
7+
using System.Runtime.InteropServices;
8+
using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces;
9+
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
10+
11+
public class NativeMethodsHelper : INativeMethodsHelper
12+
{
13+
/// <summary>
14+
/// Returns if a process is 64 bit process
15+
/// </summary>
16+
/// <param name="processHandle">Process Handle</param>
17+
/// <returns>Bool for Is64Bit</returns>
18+
public bool Is64Bit(IntPtr processHandle)
19+
{
20+
// WOW64 is the x86 emulator that allows 32 bit Windows - based applications to run seamlessly on 64 bit Windows.
21+
bool isWow64 = false;
22+
23+
// If the function succeeds, the return value is a nonzero value.
24+
if (!IsWow64Process(processHandle, out isWow64))
25+
{
26+
if (EqtTrace.IsVerboseEnabled)
27+
{
28+
EqtTrace.Verbose("NativeMethodsHelper: The call to IsWow64Process failed.");
29+
}
30+
}
31+
32+
return !isWow64;
33+
}
34+
35+
// A pointer to a value that is set to TRUE if the process is running under WOW64.
36+
// If the process is running under 32-bit Windows, the value is set to FALSE.
37+
// If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE.
38+
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
39+
[return: MarshalAs(UnmanagedType.Bool)]
40+
internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process);
41+
}
42+
}

src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcessDumpUtility.cs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector
55
{
66
using System;
7+
using System.Collections.Generic;
78
using System.Diagnostics;
8-
using System.Globalization;
99
using System.IO;
10+
using System.Text;
11+
using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces;
1012
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
1113
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions;
1214
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces;
@@ -15,27 +17,35 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector
1517

1618
public class ProcessDumpUtility : IProcessDumpUtility
1719
{
20+
private static List<string> procDumpExceptionsList;
1821
private IProcessHelper processHelper;
1922
private IFileHelper fileHelper;
2023
private IEnvironment environment;
2124
private Process procDumpProcess;
2225
private string testResultsDirectory;
2326
private string dumpFileName;
27+
private INativeMethodsHelper nativeMethodsHelper;
2428

2529
public ProcessDumpUtility()
26-
: this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment())
30+
: this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment(), new NativeMethodsHelper())
2731
{
2832
}
2933

30-
public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment)
34+
public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment, INativeMethodsHelper nativeMethodsHelper)
3135
{
3236
this.processHelper = processHelper;
3337
this.fileHelper = fileHelper;
3438
this.environment = environment;
39+
this.nativeMethodsHelper = nativeMethodsHelper;
40+
ProcessDumpUtility.procDumpExceptionsList = new List<string>()
41+
{
42+
"STACK_OVERFLOW",
43+
"ACCESS_VIOLATION"
44+
};
3545
}
3646

37-
/// <inheritdoc/>
38-
public string GetDumpFile()
47+
/// <inheritdoc/>
48+
public string GetDumpFile()
3949
{
4050
if (this.procDumpProcess == null)
4151
{
@@ -77,7 +87,7 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu
7787
this.testResultsDirectory = testResultsDirectory;
7888

7989
this.procDumpProcess = this.processHelper.LaunchProcess(
80-
this.GetProcDumpExecutable(),
90+
this.GetProcDumpExecutable(processId),
8191
ProcessDumpUtility.BuildProcDumpArgs(processId, this.dumpFileName, isFullDump),
8292
testResultsDirectory,
8393
null,
@@ -101,37 +111,57 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu
101111
private static string BuildProcDumpArgs(int processId, string filename, bool isFullDump = false)
102112
{
103113
// -accepteula: Auto accept end-user license agreement
114+
// -e: Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions.
115+
// -g: Run as a native debugger in a managed process (no interop).
104116
// -t: Write a dump when the process terminates.
117+
// -ma: Full dump argument.
118+
// -f: Filter the exceptions.
119+
StringBuilder procDumpArgument = new StringBuilder("-accepteula -e 1 -g -t ");
105120
if (isFullDump)
106121
{
107-
// This will create a fulldump of the process with specified filename
108-
return "-accepteula -t -ma " + processId + " " + filename + ".dmp";
122+
procDumpArgument.Append("-ma ");
109123
}
110-
else
124+
125+
foreach (var exceptionFilter in ProcessDumpUtility.procDumpExceptionsList)
111126
{
112-
// This will create a minidump of the process with specified filename
113-
return "-accepteula -t " + processId + " " + filename + ".dmp";
127+
procDumpArgument.Append($"-f {exceptionFilter} ");
114128
}
129+
130+
procDumpArgument.Append($"{processId} {filename}.dmp");
131+
var argument = procDumpArgument.ToString();
132+
133+
if (EqtTrace.IsInfoEnabled)
134+
{
135+
EqtTrace.Info($"ProcessDumpUtility : The procdump argument is {argument}");
136+
}
137+
138+
return argument;
115139
}
116140

117141
/// <summary>
118142
/// Get procdump executable path
119143
/// </summary>
144+
/// <param name="processId">
145+
/// Process Id
146+
/// </param>
120147
/// <returns>procdump executable path</returns>
121-
private string GetProcDumpExecutable()
148+
private string GetProcDumpExecutable(int processId)
122149
{
123150
var procdumpPath = Environment.GetEnvironmentVariable("PROCDUMP_PATH");
151+
124152
if (!string.IsNullOrWhiteSpace(procdumpPath))
125153
{
126154
string filename = string.Empty;
127155

128-
if (this.environment.Architecture == PlatformArchitecture.X64)
156+
// Launch procdump according to process architecture
157+
if (this.environment.Architecture == PlatformArchitecture.X86)
129158
{
130-
filename = "procdump64.exe";
159+
filename = Constants.ProcdumpProcess;
131160
}
132-
else if (this.environment.Architecture == PlatformArchitecture.X86)
161+
else
133162
{
134-
filename = "procdump.exe";
163+
filename = this.nativeMethodsHelper.Is64Bit(this.processHelper.GetProcessHandle(processId)) ?
164+
Constants.Procdump64Process : Constants.ProcdumpProcess;
135165
}
136166

137167
var procDumpExe = Path.Combine(procdumpPath, filename);
@@ -149,4 +179,4 @@ private string GetProcDumpExecutable()
149179
}
150180
}
151181
}
152-
}
182+
}

src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IProcessHelper.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,12 @@ public interface IProcessHelper
103103
/// </summary>
104104
/// <param name="process">Reference to process</param>
105105
void WaitForProcessExit(object process);
106+
107+
/// <summary>
108+
/// Gets the process handle for given process Id.
109+
/// </summary>
110+
/// <param name="processId">process id</param>
111+
/// <returns>Process Handle</returns>
112+
IntPtr GetProcessHandle(int processId);
106113
}
107114
}

src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions
55
{
6+
using System;
7+
using System.Diagnostics;
68
using System.IO;
79
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces;
810

@@ -13,5 +15,10 @@ public string GetCurrentProcessLocation()
1315
{
1416
return Path.GetDirectoryName(this.GetCurrentProcessFileName());
1517
}
18+
19+
public IntPtr GetProcessHandle(int processId)
20+
{
21+
return Process.GetProcessById(processId).Handle;
22+
}
1623
}
1724
}

src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions
55
{
6+
using System;
7+
using System.Diagnostics;
68
using System.IO;
79
using System.Reflection;
810
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces;
@@ -14,5 +16,13 @@ public string GetCurrentProcessLocation()
1416
{
1517
return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
1618
}
19+
20+
/// <inheritdoc/>
21+
public IntPtr GetProcessHandle(int processId)
22+
{
23+
// An IntPtr representing the value of the handle field.
24+
// If the handle has been marked invalid with SetHandleAsInvalid, this method still returns the original handle value, which can be a stale value.
25+
return Process.GetProcessById(processId).SafeHandle.DangerousGetHandle();
26+
}
1727
}
1828
}

src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/System/ProcessHelper.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions
55
{
66
using System;
77
using System.Collections.Generic;
8-
98
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces;
109

1110
/// <summary>
@@ -96,5 +95,10 @@ public void WaitForProcessExit(object process)
9695
{
9796
throw new NotImplementedException();
9897
}
98+
99+
public IntPtr GetProcessHandle(int processId)
100+
{
101+
throw new NotImplementedException();
102+
}
99103
}
100104
}

src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/ProcessHelper.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions
1111
/// <summary>
1212
/// Helper class to deal with process related functionality.
1313
/// </summary>
14-
public class ProcessHelper : IProcessHelper
14+
public partial class ProcessHelper : IProcessHelper
1515
{
1616
/// <inheritdoc/>
1717
public object LaunchProcess(
@@ -101,5 +101,10 @@ public void WaitForProcessExit(object process)
101101
{
102102
throw new NotImplementedException();
103103
}
104+
105+
public IntPtr GetProcessHandle(int processId)
106+
{
107+
throw new NotImplementedException();
108+
}
104109
}
105110
}

0 commit comments

Comments
 (0)