提交 827cd206 编写于 作者: P Patrick Nelson

Implement support for inspecting native COM objects in the new EE. The native...

Implement support for inspecting native COM objects in the new EE.  The native view of the COM object now shows up under a "Native View" node.
上级 40ac538d
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class NativeViewTests : CSharpResultProviderTestBase
{
[Fact]
public void NativeView1()
{
TestNativeView(true);
}
[Fact]
public void NativeViewManagedOnly()
{
TestNativeView(false);
}
private void TestNativeView(bool enableNativeDebugging)
{
var source =
@"using System.Collections;
class C
{
}";
using (new EnsureEnglishUICulture())
{
var assembly = GetAssembly(source);
var assemblies = ReflectionUtilities.GetMscorlibAndSystemCore(assembly);
using (ReflectionUtilities.LoadAssemblies(assemblies))
{
var runtime = new DkmClrRuntimeInstance(assemblies, enableNativeDebugging: enableNativeDebugging);
var inspectionContext = CreateDkmInspectionContext(runtimeInstance: runtime);
var type = assembly.GetType("C");
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: runtime.GetType((TypeImpl)type),
isComObject: true);
var evalResult = FormatResult("o", value, inspectionContext: inspectionContext);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult, inspectionContext);
if (enableNativeDebugging)
{
DkmLanguage language = new DkmLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
Verify(children,
EvalIntermediateResult("Native View", "{C++}(IUnknown*)0x00000001", "(IUnknown*)0x00000001", language));
}
else
{
Verify(children,
EvalFailedResult("Native View", "To inspect the native object, enable native code debugging."));
}
}
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
using System;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
internal sealed class NativeViewExpansion : Expansion
{
internal override void GetRows(
ResultProvider resultProvider,
ArrayBuilder<EvalResultDataItem> rows,
DkmInspectionContext inspectionContext,
EvalResultDataItem parent,
DkmClrValue value,
int startIndex,
int count,
bool visitAll,
ref int index)
{
if (InRange(startIndex, count, index))
{
rows.Add(GetRow(resultProvider, inspectionContext, value, parent));
}
index++;
}
private EvalResultDataItem GetRow(
ResultProvider resultProvider,
DkmInspectionContext inspectionContext,
DkmClrValue comObject,
EvalResultDataItem parent)
{
try
{
inspectionContext.RuntimeInstance.Process.GetNativeRuntimeInstance();
}
catch (DkmException)
{
// Native View requires native debugging to be enabled.
return new EvalResultDataItem(Resources.NativeView, Resources.NativeViewNotNativeDebugging);
}
var name = "(IUnknown*)0x" + string.Format(IntPtr.Size == 4 ? "{0:X8}" : "{0:X16}", comObject.NativeComPointer);
var fullName = "{C++}" + name;
return new EvalResultDataItem(
ExpansionKind.NativeView,
name: name,
typeDeclaringMember: null,
declaredType: comObject.Type.GetLmrType(),
parent: null,
value: comObject,
displayValue: null,
expansion: this,
childShouldParenthesize: false,
fullName: fullName,
childFullNamePrefixOpt: fullName,
formatSpecifiers: Formatter.NoFormatSpecifiers,
category: DkmEvaluationResultCategory.Data,
flags: DkmEvaluationResultFlags.ReadOnly,
editableValue: null,
inspectionContext: inspectionContext);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
using System;
namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public struct DkmCompilerId
{
public readonly Guid LanguageId;
public readonly Guid VendorId;
public DkmCompilerId(Guid vendorId, Guid languageId)
{
VendorId = vendorId;
LanguageId = languageId;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
using Microsoft.VisualStudio.Debugger.Evaluation;
namespace Microsoft.VisualStudio.Debugger
{
public class DkmEngineSettings
{
public DkmLanguage GetLanguage(DkmCompilerId compilerId)
{
return new DkmLanguage(compilerId);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
using Microsoft.VisualStudio.Debugger.CallStack;
namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public class DkmIntermediateEvaluationResult : DkmEvaluationResult
{
public string Expression { get; private set; }
public DkmLanguage IntermediateLanguage { get; private set; }
public DkmRuntimeInstance TargetRuntime { get; private set; }
public static DkmIntermediateEvaluationResult Create(DkmInspectionContext InspectionContext, DkmStackWalkFrame StackFrame, string Name, string FullName, string Expression, DkmLanguage IntermediateLanguage, DkmRuntimeInstance TargetRuntime, DkmDataItem DataItem)
{
DkmIntermediateEvaluationResult result = new DkmIntermediateEvaluationResult
{
InspectionContext = InspectionContext,
Name = Name,
FullName = FullName,
Expression = Expression,
IntermediateLanguage = IntermediateLanguage,
TargetRuntime = TargetRuntime
};
if (DataItem != null)
{
result.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
}
return result;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public class DkmLanguage
{
public readonly DkmCompilerId Id;
internal DkmLanguage(DkmCompilerId compilerId)
{
Id = compilerId;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
using System;
namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public static class DkmLanguageId
{
public static Guid Cpp
{
get
{
return new Guid("3A12D0B7-C26C-11D0-B442-00A0244A1DD2");
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
namespace Microsoft.VisualStudio.Debugger
{
public class DkmProcess
{
public readonly DkmEngineSettings EngineSettings = new DkmEngineSettings();
private readonly bool _nativeDebuggingEnabled;
public DkmProcess()
{
}
public DkmProcess(bool enableNativeDebugging)
{
_nativeDebuggingEnabled = enableNativeDebugging;
}
public DkmRuntimeInstance GetNativeRuntimeInstance()
{
if (!_nativeDebuggingEnabled)
{
throw new DkmException(DkmExceptionCode.E_XAPI_DATA_ITEM_NOT_FOUND);
}
return null; // Value isn't required for testing
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
namespace Microsoft.VisualStudio.Debugger
{
public class DkmRuntimeInstance
{
internal static readonly DkmProcess DefaultProcess = new DkmProcess();
internal static readonly DkmProcess ProcessWithNativeDebugging = new DkmProcess(enableNativeDebugging: true);
public readonly DkmProcess Process;
public DkmRuntimeInstance(bool enableNativeDebugging)
{
Process = enableNativeDebugging ?
ProcessWithNativeDebugging :
DefaultProcess;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
using System;
namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public static class DkmVendorId
{
public static Guid Microsoft
{
get
{
return new Guid("994B45C4-E6E9-11D2-903F-00C04FA302A1");
}
}
}
}
......@@ -103,6 +103,7 @@
<Compile Include="FormatSpecifierTests.cs" />
<Compile Include="FullNameTests.cs" />
<Compile Include="Helpers\TestTypeExtensions.cs" />
<Compile Include="NativeViewTests.cs" />
<Compile Include="ObjectIdTests.cs" />
<Compile Include="ResultsViewTests.cs" />
<Compile Include="TypeNameFormatterTests.cs" />
......
......@@ -108,6 +108,11 @@ internal sealed class MemberExpansion : Expansion
expansions.Add(staticMembersExpansion);
}
if (value.NativeComPointer != 0)
{
expansions.Add(new NativeViewExpansion());
}
if (nonPublicInstanceExpansion != null)
{
expansions.Add(nonPublicInstanceExpansion);
......
......@@ -13,6 +13,7 @@ internal enum ExpansionKind
{
Default,
Error,
NativeView,
NonPublicMembers,
PointerDereference,
RawView,
......
......@@ -87,6 +87,24 @@ internal class Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Native View.
/// </summary>
internal static string NativeView {
get {
return ResourceManager.GetString("NativeView", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to To inspect the native object, enable native code debugging..
/// </summary>
internal static string NativeViewNotNativeDebugging {
get {
return ResourceManager.GetString("NativeViewNotNativeDebugging", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Non-Public members.
/// </summary>
......
......@@ -129,6 +129,14 @@
<value>Cannot dereference '{0}'. The pointer is not valid.</value>
<comment>Invalid pointer dereference</comment>
</data>
<data name="NativeView" xml:space="preserve">
<value>Native View</value>
<comment>Native COM object expansion</comment>
</data>
<data name="NativeViewNotNativeDebugging" xml:space="preserve">
<value>To inspect the native object, enable native code debugging.</value>
<comment>Display value of Native View node when native debugging is not enabled</comment>
</data>
<data name="NonPublicMembers" xml:space="preserve">
<value>Non-Public members</value>
<comment>Non-public type members</comment>
......
......@@ -132,6 +132,7 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
Type: null,
DataItem: null));
break;
case ExpansionKind.NativeView:
case ExpansionKind.NonPublicMembers:
case ExpansionKind.StaticMembers:
completionRoutine(CreateEvaluationResult(
......@@ -215,6 +216,22 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
Type: typeName,
DataItem: dataItem);
}
else if (dataItem.Kind == ExpansionKind.NativeView)
{
// For Native View, create a DkmIntermediateEvaluationResult. This will allow the C++ EE
// to take over expansion.
DkmProcess process = inspectionContext.RuntimeInstance.Process;
DkmLanguage cpp = process.EngineSettings.GetLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
return DkmIntermediateEvaluationResult.Create(
InspectionContext: inspectionContext,
StackFrame: value.StackFrame,
Name: Resources.NativeView,
FullName: dataItem.FullName,
Expression: dataItem.Name,
IntermediateLanguage: cpp,
TargetRuntime: process.GetNativeRuntimeInstance(),
DataItem: dataItem);
}
else
{
ReadOnlyCollection<DkmCustomUIVisualizerInfo> customUIVisualizers = null;
......
......@@ -18,6 +18,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Expansion\DebuggerTypeProxyExpansion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Expansion\Expansion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Expansion\MemberExpansion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Expansion\NativeViewExpansion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Expansion\PointerDereferenceExpansion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Expansion\ResultsViewExpansion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Expansion\TypeVariablesExpansion.cs" />
......
......@@ -17,7 +17,7 @@ namespace Microsoft.VisualStudio.Debugger.Clr
internal delegate DkmClrModuleInstance GetModuleDelegate(DkmClrRuntimeInstance runtime, Assembly assembly);
public class DkmClrRuntimeInstance
public class DkmClrRuntimeInstance : DkmRuntimeInstance
{
internal static readonly DkmClrRuntimeInstance DefaultRuntime = new DkmClrRuntimeInstance(new Assembly[0]);
......@@ -30,7 +30,9 @@ public class DkmClrRuntimeInstance
internal DkmClrRuntimeInstance(
Assembly[] assemblies,
GetModuleDelegate getModule = null,
GetMemberValueDelegate getMemberValue = null)
GetMemberValueDelegate getMemberValue = null,
bool enableNativeDebugging = false)
: base(enableNativeDebugging)
{
if (getModule == null)
{
......
......@@ -30,7 +30,8 @@ public class DkmClrValue : DkmDataContainer
string alias,
IDkmClrFormatter formatter,
DkmEvaluationResultFlags evalFlags,
DkmClrValueFlags valueFlags)
DkmClrValueFlags valueFlags,
bool isComObject = false)
{
Debug.Assert(!type.GetLmrType().IsTypeVariables() || (valueFlags == DkmClrValueFlags.Synthetic));
Debug.Assert((alias == null) || evalFlags.Includes(DkmEvaluationResultFlags.HasObjectId));
......@@ -44,6 +45,7 @@ public class DkmClrValue : DkmDataContainer
this.Alias = alias;
this.EvalFlags = evalFlags;
this.ValueFlags = valueFlags;
this.NativeComPointer = isComObject ? 1UL : 0;
}
public readonly DkmEvaluationResultFlags EvalFlags;
......@@ -57,6 +59,7 @@ public class DkmClrValue : DkmDataContainer
public readonly DkmDataAddress Address;
public readonly object HostObjectValue;
public readonly string Alias;
public readonly ulong NativeComPointer;
private readonly IDkmClrFormatter _formatter;
private readonly object _rawValue;
......
......@@ -18,16 +18,18 @@ namespace Microsoft.VisualStudio.Debugger.Evaluation
[Guid("0807c826-3338-dd99-2f3a-202ba8fb9da7")]
public class DkmInspectionContext
{
internal DkmInspectionContext(IDkmClrFormatter formatter, DkmEvaluationFlags evaluationFlags, uint radix)
internal DkmInspectionContext(IDkmClrFormatter formatter, DkmEvaluationFlags evaluationFlags, uint radix, DkmRuntimeInstance runtimeInstance = null)
{
_formatter = formatter;
this.EvaluationFlags = evaluationFlags;
this.Radix = radix;
this.RuntimeInstance = runtimeInstance ?? DkmClrRuntimeInstance.DefaultRuntime;
}
private readonly IDkmClrFormatter _formatter;
public readonly DkmEvaluationFlags EvaluationFlags;
public readonly DkmRuntimeInstance RuntimeInstance;
//
// Summary:
......
......@@ -54,7 +54,8 @@ internal ResultProviderTestBase(ResultProvider resultProvider, DkmInspectionCont
DkmClrType type,
string alias = null,
DkmEvaluationResultFlags evalFlags = DkmEvaluationResultFlags.None,
DkmClrValueFlags valueFlags = DkmClrValueFlags.None)
DkmClrValueFlags valueFlags = DkmClrValueFlags.None,
bool isComObject = false)
{
return new DkmClrValue(
value,
......@@ -63,7 +64,8 @@ internal ResultProviderTestBase(ResultProvider resultProvider, DkmInspectionCont
alias,
_formatter,
evalFlags,
valueFlags);
valueFlags,
isComObject);
}
internal DkmClrValue CreateErrorValue(
......@@ -128,14 +130,21 @@ internal DkmClrValue GetValueForUnderlyingString(object value, Type type)
#region ResultProvider Tests
internal DkmInspectionContext CreateDkmInspectionContext(DkmEvaluationFlags flags = DkmEvaluationFlags.None, uint radix = 10)
internal DkmInspectionContext CreateDkmInspectionContext(
DkmEvaluationFlags flags = DkmEvaluationFlags.None,
uint radix = 10,
DkmRuntimeInstance runtimeInstance = null)
{
return CreateDkmInspectionContext(_formatter, flags, radix);
return CreateDkmInspectionContext(_formatter, flags, radix, runtimeInstance);
}
internal static DkmInspectionContext CreateDkmInspectionContext(IDkmClrFormatter formatter, DkmEvaluationFlags flags, uint radix)
internal static DkmInspectionContext CreateDkmInspectionContext(
IDkmClrFormatter formatter,
DkmEvaluationFlags flags,
uint radix,
DkmRuntimeInstance runtimeInstance = null)
{
return new DkmInspectionContext(formatter, flags, radix);
return new DkmInspectionContext(formatter, flags, radix, runtimeInstance);
}
internal DkmEvaluationResult FormatResult(string name, DkmClrValue value, DkmClrType declaredType = null, DkmInspectionContext inspectionContext = null)
......@@ -256,6 +265,23 @@ internal DkmEvaluationResult[] GetItems(DkmEvaluationResultEnumContext enumConte
null);
}
internal static DkmIntermediateEvaluationResult EvalIntermediateResult(
string name,
string fullName,
string expression,
DkmLanguage language)
{
return DkmIntermediateEvaluationResult.Create(
InspectionContext: null,
StackFrame: null,
Name: name,
FullName: fullName,
Expression: expression,
IntermediateLanguage: language,
TargetRuntime: null,
DataItem: null);
}
internal static DkmEvaluationResult EvalFailedResult(
string name,
string message,
......@@ -339,6 +365,7 @@ internal static void Verify(DkmEvaluationResult actual, DkmEvaluationResult expe
Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.FullName, actual.FullName);
var expectedSuccess = expected as DkmSuccessEvaluationResult;
var expectedIntermediate = expected as DkmIntermediateEvaluationResult;
if (expectedSuccess != null)
{
var actualSuccess = (DkmSuccessEvaluationResult)actual;
......@@ -353,6 +380,13 @@ internal static void Verify(DkmEvaluationResult actual, DkmEvaluationResult expe
(expectedSuccess.CustomUIVisualizers != null && actualSuccess.CustomUIVisualizers != null &&
expectedSuccess.CustomUIVisualizers.SequenceEqual(actualSuccess.CustomUIVisualizers, CustomUIVisualizerInfoComparer.Instance)));
}
else if (expectedIntermediate != null)
{
var actualIntermediate = (DkmIntermediateEvaluationResult)actual;
Assert.Equal(expectedIntermediate.Expression, actualIntermediate.Expression);
Assert.Equal(expectedIntermediate.IntermediateLanguage.Id.LanguageId, actualIntermediate.IntermediateLanguage.Id.LanguageId);
Assert.Equal(expectedIntermediate.IntermediateLanguage.Id.VendorId, actualIntermediate.IntermediateLanguage.Id.VendorId);
}
else
{
var actualFailed = (DkmFailedEvaluationResult)actual;
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="Settings">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" />
......@@ -83,7 +84,9 @@
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Debugger\Engine\DkmCompilerId.cs" />
<Compile Include="Debugger\Engine\DkmContinueCorruptingException.cs" />
<Compile Include="Debugger\Engine\DkmEngineSettings.cs" />
<Compile Include="Debugger\Engine\DkmEvaluateDebuggerDisplayStringAsyncResult.cs" />
<Compile Include="Debugger\Engine\DkmEvaluationAsyncResult.cs" />
<Compile Include="Debugger\Engine\DkmExceptionCode.cs" />
......@@ -111,11 +114,17 @@
<Compile Include="Debugger\Engine\DkmFailedEvaluationResult.cs" />
<Compile Include="Debugger\Engine\DkmInspectionContext.cs" />
<Compile Include="Debugger\Engine\DkmDataItem.cs" />
<Compile Include="Debugger\Engine\DkmIntermediateEvaluationResult.cs" />
<Compile Include="Debugger\Engine\DkmLanguage.cs" />
<Compile Include="Debugger\Engine\DkmLanguageId.cs" />
<Compile Include="Debugger\Engine\DkmMisc.cs" />
<Compile Include="Debugger\Engine\DkmModule.cs" />
<Compile Include="Debugger\Engine\DkmModuleInstance.cs" />
<Compile Include="Debugger\Engine\DkmProcess.cs" />
<Compile Include="Debugger\Engine\DkmReportNonFatalWatsonExceptionAttribute.cs" />
<Compile Include="Debugger\Engine\DkmRuntimeInstance.cs" />
<Compile Include="Debugger\Engine\DkmSuccessEvaluationResult.cs" />
<Compile Include="Debugger\Engine\DkmVendorId.cs" />
<Compile Include="Debugger\Engine\DkmWorkList.cs" />
<Compile Include="Debugger\Engine\IDkmClrFormatter.cs" />
<Compile Include="Debugger\Engine\IDkmClrResultProvider.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册