Merge pull request #2051 from livarcocc/portable_pdb
Support portable pdbs in Testing.Abstractions
This commit is contained in:
commit
3fe46df8b4
54 changed files with 998 additions and 2555 deletions
|
@ -85,6 +85,16 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Cli.Utils.
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RuntimeGraphGenerator", "tools\RuntimeGraphGenerator\RuntimeGraphGenerator.xproj", "{EFC4FE68-83EB-40E4-BFA8-61D0B4626F25}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestingAbstractions", "TestingAbstractions", "{EB0F5F8C-0991-49AC-B188-A9869476C7DF}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithFullPdbs", "test\TestingAbstractions\TestAppWithFullPdbs\TestAppWithFullPdbs.xproj", "{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithPortablePdbs", "test\TestingAbstractions\TestAppWithPortablePdbs\TestAppWithPortablePdbs.xproj", "{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testing.Abstractions.Tests", "test\TestingAbstractions\Microsoft.Extensions.Testing.Abstractions.Tests\Microsoft.Extensions.Testing.Abstractions.Tests.xproj", "{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testing.Abstractions.UnitTests", "test\TestingAbstractions\Microsoft.Extensions.Testing.Abstractions.UnitTests\Microsoft.Extensions.Testing.Abstractions.UnitTests.xproj", "{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -609,6 +619,70 @@ Global
|
|||
{EFC4FE68-83EB-40E4-BFA8-61D0B4626F25}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{EFC4FE68-83EB-40E4-BFA8-61D0B4626F25}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{EFC4FE68-83EB-40E4-BFA8-61D0B4626F25}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -648,5 +722,10 @@ Global
|
|||
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726} = {88278B81-7649-45DC-8A6A-D3A645C5AFC3}
|
||||
{09C52F96-EFDD-4448-95EC-6D362DD60BAA} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{EFC4FE68-83EB-40E4-BFA8-61D0B4626F25} = {0722D325-24C8-4E83-B5AF-0A083E7F0749}
|
||||
{EB0F5F8C-0991-49AC-B188-A9869476C7DF} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{0A37AB59-BDB5-4957-9BB8-D965F9A67A5B} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
|
||||
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
|
||||
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
|
||||
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
internal sealed class ComStreamWrapper : IStream
|
||||
{
|
||||
private readonly Stream _stream;
|
||||
|
||||
public ComStreamWrapper(Stream stream)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(stream.CanSeek);
|
||||
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
public void Commit(int grfCommitFlags)
|
||||
{
|
||||
_stream.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The actual number of bytes read can be fewer than the number of bytes requested
|
||||
/// if an error occurs or if the end of the stream is reached during the read operation.
|
||||
/// </summary>
|
||||
public unsafe void Read(byte[] pv, int cb, IntPtr pcbRead)
|
||||
{
|
||||
int bytesRead = _stream.Read(pv, 0, cb);
|
||||
|
||||
if (pcbRead != IntPtr.Zero)
|
||||
{
|
||||
*(int*)pcbRead = bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void Seek(long dlibMove, int origin, IntPtr plibNewPosition)
|
||||
{
|
||||
long newPosition = _stream.Seek(dlibMove, (SeekOrigin)origin);
|
||||
if (plibNewPosition != IntPtr.Zero)
|
||||
{
|
||||
*(long*)plibNewPosition = newPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSize(long libNewSize)
|
||||
{
|
||||
_stream.SetLength(libNewSize);
|
||||
}
|
||||
|
||||
public void Stat(out STATSTG pstatstg, int grfStatFlag)
|
||||
{
|
||||
pstatstg = new STATSTG()
|
||||
{
|
||||
cbSize = _stream.Length
|
||||
};
|
||||
}
|
||||
|
||||
public unsafe void Write(byte[] pv, int cb, IntPtr pcbWritten)
|
||||
{
|
||||
_stream.Write(pv, 0, cb);
|
||||
if (pcbWritten != IntPtr.Zero)
|
||||
{
|
||||
*(int*)pcbWritten = cb;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clone(out IStream ppstm)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void LockRegion(long libOffset, long cb, int lockType)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void UnlockRegion(long libOffset, long cb, int lockType)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
public enum DataKind
|
||||
{
|
||||
DataIsUnknown,
|
||||
DataIsLocal,
|
||||
DataIsStaticLocal,
|
||||
DataIsParam,
|
||||
DataIsObjectPtr,
|
||||
DataIsFileStatic,
|
||||
DataIsGlobal,
|
||||
DataIsMember,
|
||||
DataIsStaticMember,
|
||||
DataIsConstant
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[ComImport]
|
||||
[Guid("E6756135-1E65-4D17-8576-610761398C3C")]
|
||||
public class DiaDataSource
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("79F1BB5F-B66E-48E5-B6A9-1545C323CA3D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaDataSource
|
||||
{
|
||||
[DispId(1)]
|
||||
string lastError
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
|
||||
void loadDataFromPdb([MarshalAs(UnmanagedType.LPWStr)] [In] string pdbPath);
|
||||
|
||||
void loadAndValidateDataFromPdb([MarshalAs(UnmanagedType.LPWStr)] [In] string pdbPath, [In] ref Guid pcsig70, [In] uint sig, [In] uint age);
|
||||
|
||||
void loadDataForExe([MarshalAs(UnmanagedType.LPWStr)] [In] string executable, [MarshalAs(UnmanagedType.LPWStr)] [In] string searchPath, [MarshalAs(UnmanagedType.IUnknown)] [In] object pCallback);
|
||||
|
||||
void loadDataFromIStream([MarshalAs(UnmanagedType.Interface)] [In] IStream pIStream);
|
||||
|
||||
void openSession([MarshalAs(UnmanagedType.Interface)] out IDiaSession ppSession);
|
||||
|
||||
void loadDataFromCodeViewInfo([MarshalAs(UnmanagedType.LPWStr)] [In] string executable, [MarshalAs(UnmanagedType.LPWStr)] [In] string searchPath, [In] uint cbCvInfo, [In] ref byte pbCvInfo, [MarshalAs(UnmanagedType.IUnknown)] [In] object pCallback);
|
||||
|
||||
void loadDataFromMiscInfo([MarshalAs(UnmanagedType.LPWStr)] [In] string executable, [MarshalAs(UnmanagedType.LPWStr)] [In] string searchPath, [In] uint timeStampExe, [In] uint timeStampDbg, [In] uint sizeOfExe, [In] uint cbMiscInfo, [In] ref byte pbMiscInfo, [MarshalAs(UnmanagedType.IUnknown)] [In] object pCallback);
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("486943E8-D187-4A6B-A3C4-291259FFF60D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumDebugStreamData
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(2)]
|
||||
string name
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
void Item([In] uint index, [In] uint cbData, out uint pcbData, out byte pbData);
|
||||
|
||||
void Next([In] uint celt, [In] uint cbData, out uint pcbData, out byte pbData, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreamData ppenum);
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("08CBB41E-47A6-4F87-92F1-1C9C87CED044"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumDebugStreams
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaEnumDebugStreamData Item([In] object index);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreamData rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreams ppenum);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("D5612573-6925-4468-8883-98CDEC8C384A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumInjectedSources
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaInjectedSource Item([In] uint index);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaInjectedSource rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumInjectedSources ppenum);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("1C7FF653-51F7-457E-8419-B20F57EF7E4D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumInputAssemblyFiles
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaInputAssemblyFile Item([In] uint index);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaInputAssemblyFile rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumInputAssemblyFiles ppenum);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("FE30E878-54AC-44F1-81BA-39DE940F6052"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumLineNumbers
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaLineNumber Item([In] uint index);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaLineNumber rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppenum);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("10F3DBD9-664F-4469-B808-9471C7A50538"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumSourceFiles
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaSourceFile Item([In] uint index);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSourceFile rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSourceFiles ppenum);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("CAB72C48-443B-48F5-9B0B-42F0820AB29A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumSymbols
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaSymbol Item([In] uint index);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppenum);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("624B7D9C-24EA-4421-9D06-3B577471C1FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumSymbolsByAddr
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaSymbol symbolByAddr([In] uint isect, [In] uint offset);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaSymbol symbolByRVA([In] uint relativeVirtualAddress);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaSymbol symbolByVA([In] ulong virtualAddress);
|
||||
|
||||
void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol rgelt, out uint pceltFetched);
|
||||
|
||||
void Prev([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol rgelt, out uint pceltFetched);
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbolsByAddr ppenum);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[DefaultMember("Item"), Guid("C65C2B0A-1150-4D7A-AFCC-E05BF3DEE81E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaEnumTables
|
||||
{
|
||||
[DispId(1)]
|
||||
int count
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IDiaTable Item([In] object index);
|
||||
|
||||
void Next(uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaTable rgelt, ref uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumTables ppenum);
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("AE605CDC-8105-4A23-B710-3259F1E26112"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaInjectedSource
|
||||
{
|
||||
[DispId(1)]
|
||||
uint crc
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(2)]
|
||||
ulong length
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(3)]
|
||||
string fileName
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
[DispId(4)]
|
||||
string objectFileName
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
[DispId(5)]
|
||||
string virtualFilename
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
[DispId(6)]
|
||||
uint sourceCompression
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
|
||||
void get_source([In] uint cbData, out uint pcbData, out byte pbData);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("3BFE56B0-390C-4863-9430-1F3D083B7684"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaInputAssemblyFile
|
||||
{
|
||||
[DispId(1)]
|
||||
uint uniqueId
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(2)]
|
||||
uint index
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(3)]
|
||||
uint timeStamp
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(4)]
|
||||
int pdbAvailableAtILMerge
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(5)]
|
||||
string fileName
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
|
||||
void get_version([In] uint cbData, out uint pcbData, out byte pbData);
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("B388EB14-BE4D-421D-A8A1-6CF7AB057086"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaLineNumber
|
||||
{
|
||||
[DispId(1)]
|
||||
IDiaSymbol compiland
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
get;
|
||||
}
|
||||
[DispId(2)]
|
||||
IDiaSourceFile sourceFile
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
get;
|
||||
}
|
||||
[DispId(3)]
|
||||
uint lineNumber
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(4)]
|
||||
uint lineNumberEnd
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(5)]
|
||||
uint columnNumber
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(6)]
|
||||
uint columnNumberEnd
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(7)]
|
||||
uint addressSection
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(8)]
|
||||
uint addressOffset
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(9)]
|
||||
uint relativeVirtualAddress
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(10)]
|
||||
ulong virtualAddress
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(11)]
|
||||
uint length
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(12)]
|
||||
uint sourceFileId
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(13)]
|
||||
int statement
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(14)]
|
||||
uint compilandId
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("2F609EE1-D1C8-4E24-8288-3326BADCD211"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaSession
|
||||
{
|
||||
[DispId(1)]
|
||||
ulong loadAddress
|
||||
{
|
||||
|
||||
get;
|
||||
|
||||
set;
|
||||
}
|
||||
[DispId(2)]
|
||||
IDiaSymbol globalScope
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
get;
|
||||
}
|
||||
|
||||
void getEnumTables([MarshalAs(UnmanagedType.Interface)] out IDiaEnumTables ppEnumTables);
|
||||
|
||||
void getSymbolsByAddr([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbolsByAddr ppEnumbyAddr);
|
||||
|
||||
void findChildren([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findChildrenEx([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findChildrenExByAddr([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] uint isect, [In] uint offset, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findChildrenExByVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] ulong va, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findChildrenExByRVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] uint rva, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findSymbolByAddr([In] uint isect, [In] uint offset, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol);
|
||||
|
||||
void findSymbolByRVA([In] uint rva, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol);
|
||||
|
||||
void findSymbolByVA([In] ulong va, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol);
|
||||
|
||||
void findSymbolByToken([In] uint token, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol);
|
||||
|
||||
void symsAreEquiv([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol symbolA, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol symbolB);
|
||||
|
||||
void symbolById([In] uint id, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol);
|
||||
|
||||
void findSymbolByRVAEx([In] uint rva, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol, out int displacement);
|
||||
|
||||
void findSymbolByVAEx([In] ulong va, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol, out int displacement);
|
||||
|
||||
void findFile([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol pCompiland, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSourceFiles ppResult);
|
||||
|
||||
void findFileById([In] uint uniqueId, [MarshalAs(UnmanagedType.Interface)] out IDiaSourceFile ppResult);
|
||||
|
||||
void findLines([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol compiland, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSourceFile file, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findLinesByAddr([In] uint seg, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findLinesByRVA([In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findLinesByVA([In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findLinesByLinenum([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol compiland, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSourceFile file, [In] uint linenum, [In] uint column, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInjectedSource([MarshalAs(UnmanagedType.LPWStr)] [In] string srcFile, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumInjectedSources ppResult);
|
||||
|
||||
void getEnumDebugStreams([MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreams ppEnumDebugStreams);
|
||||
|
||||
void findInlineFramesByAddr([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint isect, [In] uint offset, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findInlineFramesByRVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint rva, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findInlineFramesByVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] ulong va, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void findInlineeLines([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInlineeLinesByAddr([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint isect, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInlineeLinesByRVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInlineeLinesByVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInlineeLinesByLinenum([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol compiland, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSourceFile file, [In] uint linenum, [In] uint column, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInlineesByName([MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint option, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void addressForVA([In] ulong va, out uint pISect, out uint pOffset);
|
||||
|
||||
void addressForRVA([In] uint rva, out uint pISect, out uint pOffset);
|
||||
|
||||
void findILOffsetsByAddr([In] uint isect, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findILOffsetsByRVA([In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findILOffsetsByVA([In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult);
|
||||
|
||||
void findInputAssemblyFiles([MarshalAs(UnmanagedType.Interface)] out IDiaEnumInputAssemblyFiles ppResult);
|
||||
|
||||
void findInputAssembly([In] uint index, [MarshalAs(UnmanagedType.Interface)] out IDiaInputAssemblyFile ppResult);
|
||||
|
||||
void findInputAssemblyById([In] uint uniqueId, [MarshalAs(UnmanagedType.Interface)] out IDiaInputAssemblyFile ppResult);
|
||||
|
||||
void getFuncMDTokenMapSize(out uint pcb);
|
||||
|
||||
void getFuncMDTokenMap([In] uint cb, out uint pcb, out byte pb);
|
||||
|
||||
void getTypeMDTokenMapSize(out uint pcb);
|
||||
|
||||
void getTypeMDTokenMap([In] uint cb, out uint pcb, out byte pb);
|
||||
|
||||
void getNumberOfFunctionFragments_VA([In] ulong vaFunc, [In] uint cbFunc, out uint pNumFragments);
|
||||
|
||||
void getNumberOfFunctionFragments_RVA([In] uint rvaFunc, [In] uint cbFunc, out uint pNumFragments);
|
||||
|
||||
void getFunctionFragments_VA([In] ulong vaFunc, [In] uint cbFunc, [In] uint cFragments, out ulong pVaFragment, out uint pLenFragment);
|
||||
|
||||
void getFunctionFragments_RVA([In] uint rvaFunc, [In] uint cbFunc, [In] uint cFragments, out uint pRvaFragment, out uint pLenFragment);
|
||||
|
||||
void getExports([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
|
||||
void getHeapAllocationSites([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult);
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("A2EF5353-F5A8-4EB3-90D2-CB526ACB3CDD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaSourceFile
|
||||
{
|
||||
[DispId(2)]
|
||||
uint uniqueId
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(3)]
|
||||
string fileName
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
get;
|
||||
}
|
||||
[DispId(4)]
|
||||
uint checksumType
|
||||
{
|
||||
|
||||
get;
|
||||
}
|
||||
[DispId(5)]
|
||||
IDiaEnumSymbols compilands
|
||||
{
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
get;
|
||||
}
|
||||
|
||||
|
||||
void get_checksum([In] uint cbData, out uint pcbData, out byte pbData);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[TypeIdentifier]
|
||||
[CompilerGenerated]
|
||||
[DefaultMember("Item"), Guid("4A59FB77-ABAC-469B-A30B-9ECC85BFEF14"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IDiaTable : IEnumUnknown
|
||||
{
|
||||
string name { get; }
|
||||
|
||||
[DispId(2)]
|
||||
int count
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
new void RemoteNext([In] uint celt, [MarshalAs(UnmanagedType.IUnknown)] out object rgelt, out uint pceltFetched);
|
||||
|
||||
new void Skip([In] uint celt);
|
||||
|
||||
new void Reset();
|
||||
|
||||
new void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumUnknown ppenum);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.IUnknown, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")]
|
||||
IEnumerator GetEnumerator();
|
||||
|
||||
|
||||
[return: MarshalAs(UnmanagedType.IUnknown)]
|
||||
object Item([In] uint index);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("00000100-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IEnumUnknown
|
||||
{
|
||||
void RemoteNext([In] uint celt, [MarshalAs(UnmanagedType.IUnknown)] out object rgelt, out uint pceltFetched);
|
||||
|
||||
void Skip([In] uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumUnknown ppenum);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("0C733A30-2A1C-11CE-ADE5-00AA0044773D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface ISequentialStream
|
||||
{
|
||||
|
||||
void RemoteRead([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, out uint pcbRead);
|
||||
|
||||
void RemoteWrite([In] ref byte pv, [In] uint cb, out uint pcbWritten);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[Guid("0000000C-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComImport]
|
||||
public interface IStream : ISequentialStream
|
||||
{
|
||||
new void RemoteRead([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, out uint pcbRead);
|
||||
|
||||
new void RemoteWrite([In] ref byte pv, [In] uint cb, out uint pcbWritten);
|
||||
|
||||
void RemoteSeek([In] _LARGE_INTEGER dlibMove, [In] uint dwOrigin, out _ULARGE_INTEGER plibNewPosition);
|
||||
|
||||
void SetSize([In] _ULARGE_INTEGER libNewSize);
|
||||
|
||||
void RemoteCopyTo([MarshalAs(UnmanagedType.Interface)] [In] IStream pstm, [In] _ULARGE_INTEGER cb, out _ULARGE_INTEGER pcbRead, out _ULARGE_INTEGER pcbWritten);
|
||||
|
||||
void Commit([In] uint grfCommitFlags);
|
||||
|
||||
void Revert();
|
||||
|
||||
void LockRegion([In] _ULARGE_INTEGER libOffset, [In] _ULARGE_INTEGER cb, [In] uint dwLockType);
|
||||
|
||||
void UnlockRegion([In] _ULARGE_INTEGER libOffset, [In] _ULARGE_INTEGER cb, [In] uint dwLockType);
|
||||
|
||||
void Stat(out tagSTATSTG pstatstg, [In] uint grfStatFlag);
|
||||
|
||||
void Clone([MarshalAs(UnmanagedType.Interface)] out IStream ppstm);
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
public class StreamWrapper : IStream
|
||||
{
|
||||
private Stream _stream;
|
||||
|
||||
public StreamWrapper(Stream stream)
|
||||
{
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
public void RemoteRead(byte[] pv, int cb, out uint pcbRead)
|
||||
{
|
||||
pcbRead = (uint)_stream.Read(pv, 0, cb);
|
||||
}
|
||||
|
||||
public void Stat(out tagSTATSTG pstatstg, [In]uint grfStatFlag)
|
||||
{
|
||||
pstatstg = new tagSTATSTG();
|
||||
pstatstg.cbSize.QuadPart = (ulong)_stream.Length;
|
||||
}
|
||||
|
||||
public void RemoteSeek([In]_LARGE_INTEGER dlibMove, [In]uint dwOrigin, out _ULARGE_INTEGER plibNewPosition)
|
||||
{
|
||||
plibNewPosition.QuadPart = (ulong)_stream.Seek(dlibMove.QuadPart, (SeekOrigin)dwOrigin);
|
||||
}
|
||||
|
||||
public void RemoteRead(byte[] pv, [In]uint cb, out uint pcbRead)
|
||||
{
|
||||
pcbRead = (uint)_stream.Read(pv, offset: 0, count: (int)cb);
|
||||
}
|
||||
|
||||
public void SetSize([In]_ULARGE_INTEGER libNewSize)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoteCopyTo([In, MarshalAs(UnmanagedType.Interface)]IStream pstm, [In]_ULARGE_INTEGER cb, out _ULARGE_INTEGER pcbRead, out _ULARGE_INTEGER pcbWritten)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Commit([In]uint grfCommitFlags)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void LockRegion([In]_ULARGE_INTEGER libOffset, [In]_ULARGE_INTEGER cb, [In]uint dwLockType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void UnlockRegion([In]_ULARGE_INTEGER libOffset, [In]_ULARGE_INTEGER cb, [In]uint dwLockType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Clone([MarshalAs(UnmanagedType.Interface)]out IStream ppstm)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoteWrite([In]ref byte pv, [In]uint cb, out uint pcbWritten)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct _LARGE_INTEGER
|
||||
{
|
||||
public long QuadPart;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct _ULARGE_INTEGER
|
||||
{
|
||||
public ulong QuadPart;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct tagSTATSTG
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pwcsName;
|
||||
public uint type;
|
||||
public _ULARGE_INTEGER cbSize;
|
||||
public _FILETIME mtime;
|
||||
public _FILETIME ctime;
|
||||
public _FILETIME atime;
|
||||
public uint grfMode;
|
||||
public uint grfLocksSupported;
|
||||
public Guid clsid;
|
||||
public uint grfStateBits;
|
||||
public uint reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public struct _FILETIME
|
||||
{
|
||||
public uint dwLowDateTime;
|
||||
public uint dwHighDateTime;
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace dia2
|
||||
{
|
||||
public enum SymTagEnum
|
||||
{
|
||||
SymTagNull,
|
||||
SymTagExe,
|
||||
SymTagCompiland,
|
||||
SymTagCompilandDetails,
|
||||
SymTagCompilandEnv,
|
||||
SymTagFunction,
|
||||
SymTagBlock,
|
||||
SymTagData,
|
||||
SymTagAnnotation,
|
||||
SymTagLabel,
|
||||
SymTagPublicSymbol,
|
||||
SymTagUDT,
|
||||
SymTagEnum,
|
||||
SymTagFunctionType,
|
||||
SymTagPointerType,
|
||||
SymTagArrayType,
|
||||
SymTagBaseType,
|
||||
SymTagTypedef,
|
||||
SymTagBaseClass,
|
||||
SymTagFriend,
|
||||
SymTagFunctionArgType,
|
||||
SymTagFuncDebugStart,
|
||||
SymTagFuncDebugEnd,
|
||||
SymTagUsingNamespace,
|
||||
SymTagVTableShape,
|
||||
SymTagVTable,
|
||||
SymTagCustom,
|
||||
SymTagThunk,
|
||||
SymTagCustomType,
|
||||
SymTagManagedType,
|
||||
SymTagDimension,
|
||||
SymTagCallSite,
|
||||
SymTagInlineSite,
|
||||
SymTagBaseInterface,
|
||||
SymTagVectorType,
|
||||
SymTagMatrixType,
|
||||
SymTagHLSLType,
|
||||
SymTagCaller,
|
||||
SymTagCallee,
|
||||
SymTagExport,
|
||||
SymTagHeapAllocationSite,
|
||||
SymTagMax
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.DiaSymReader;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public class FullPdbReader : IPdbReader
|
||||
{
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
[DllImport("Microsoft.DiaSymReader.Native.x86.dll", EntryPoint = "CreateSymReader")]
|
||||
private extern static void CreateSymReader32(ref Guid id, [MarshalAs(UnmanagedType.IUnknown)]out object symReader);
|
||||
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
[DllImport("Microsoft.DiaSymReader.Native.amd64.dll", EntryPoint = "CreateSymReader")]
|
||||
private extern static void CreateSymReader64(ref Guid id, [MarshalAs(UnmanagedType.IUnknown)]out object symReader);
|
||||
|
||||
private readonly ISymUnmanagedReader3 _symReader;
|
||||
|
||||
public FullPdbReader(Stream pdbStream)
|
||||
{
|
||||
pdbStream.Position = 0;
|
||||
|
||||
_symReader = CreateNativeSymReader(pdbStream);
|
||||
}
|
||||
|
||||
public SourceInformation GetSourceInformation(MethodInfo methodInfo)
|
||||
{
|
||||
if (methodInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var methodToken = methodInfo.GetMethodToken();
|
||||
|
||||
var method = GetMethod(methodToken);
|
||||
|
||||
return method?.GetSourceInformation();
|
||||
}
|
||||
|
||||
private ISymUnmanagedMethod GetMethod(int methodToken)
|
||||
{
|
||||
ISymUnmanagedMethod method;
|
||||
_symReader.GetMethod(methodToken, out method);
|
||||
return method;
|
||||
}
|
||||
|
||||
private static ISymUnmanagedReader3 CreateNativeSymReader(Stream pdbStream)
|
||||
{
|
||||
object symReader = null;
|
||||
var guid = default(Guid);
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
CreateSymReader32(ref guid, out symReader);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateSymReader64(ref guid, out symReader);
|
||||
}
|
||||
var reader = (ISymUnmanagedReader3)symReader;
|
||||
var hr = reader.Initialize(new DummyMetadataImport(), null, null, new ComStreamWrapper(pdbStream));
|
||||
SymUnmanagedReaderExtensions.ThrowExceptionForHR(hr);
|
||||
return reader;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
((ISymUnmanagedDispose) _symReader).Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
[ComVisible(false)]
|
||||
[ComImport]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44")]
|
||||
interface IMetadataImport { }
|
||||
|
||||
class DummyMetadataImport : IMetadataImport { }
|
||||
}
|
13
src/Microsoft.Extensions.Testing.Abstractions/IPdbReader.cs
Normal file
13
src/Microsoft.Extensions.Testing.Abstractions/IPdbReader.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public interface IPdbReader : IDisposable
|
||||
{
|
||||
SourceInformation GetSourceInformation(MethodInfo methodInfo);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public interface IPdbReaderFactory
|
||||
{
|
||||
IPdbReader Create(string pdbPath);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public interface ISourceInformationProvider
|
||||
public interface ISourceInformationProvider : IDisposable
|
||||
{
|
||||
SourceInformation GetSourceInformation(MethodInfo method);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
internal static class MetadataExtensions
|
||||
{
|
||||
internal static int GetMethodToken(this MethodInfo methodInfo)
|
||||
{
|
||||
#if NETSTANDARD1_3
|
||||
var methodToken = methodInfo.GetMetadataToken();
|
||||
#else
|
||||
var methodToken = methodInfo.MetadataToken;
|
||||
#endif
|
||||
|
||||
return methodToken;
|
||||
}
|
||||
|
||||
internal static MethodDebugInformationHandle GetMethodDebugInformationHandle(this MethodInfo methodInfo)
|
||||
{
|
||||
var methodToken = methodInfo.GetMethodToken();
|
||||
var handle = ((MethodDefinitionHandle)MetadataTokens.Handle(methodToken)).ToDebugInformationHandle();
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public class PdbReaderFactory : IPdbReaderFactory
|
||||
{
|
||||
public IPdbReader Create(string pdbPath)
|
||||
{
|
||||
var pdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
if (IsPortable(pdbStream))
|
||||
{
|
||||
return new PortablePdbReader(pdbStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new FullPdbReader(pdbStream);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsPortable(Stream pdbStream)
|
||||
{
|
||||
return pdbStream.ReadByte() == 'B' &&
|
||||
pdbStream.ReadByte() == 'S' &&
|
||||
pdbStream.ReadByte() == 'J' &&
|
||||
pdbStream.ReadByte() == 'B';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public class PortablePdbReader : IPdbReader
|
||||
{
|
||||
private MetadataReader _reader;
|
||||
private GCHandle _gcHandle;
|
||||
|
||||
public PortablePdbReader(Stream pdbStream)
|
||||
{
|
||||
pdbStream.Position = 0;
|
||||
var buffer = new byte[pdbStream.Length];
|
||||
pdbStream.Read(buffer, 0, buffer.Length);
|
||||
|
||||
_gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
unsafe
|
||||
{
|
||||
var address = _gcHandle.AddrOfPinnedObject();
|
||||
_reader = new MetadataReader((byte*)address.ToPointer(), buffer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public SourceInformation GetSourceInformation(MethodInfo methodInfo)
|
||||
{
|
||||
if (methodInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var handle = methodInfo.GetMethodDebugInformationHandle();
|
||||
|
||||
return GetSourceInformation(handle);
|
||||
}
|
||||
|
||||
private SourceInformation GetSourceInformation(MethodDebugInformationHandle handle)
|
||||
{
|
||||
SourceInformation sourceInformation = null;
|
||||
try
|
||||
{
|
||||
var methodDebugDefinition = _reader.GetMethodDebugInformation(handle);
|
||||
var fileName = GetMethodFileName(methodDebugDefinition);
|
||||
var lineNumber = GetMethodStartLineNumber(methodDebugDefinition);
|
||||
|
||||
sourceInformation = new SourceInformation(fileName, lineNumber);
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
}
|
||||
|
||||
return sourceInformation;
|
||||
}
|
||||
|
||||
private static int GetMethodStartLineNumber(MethodDebugInformation methodDebugDefinition)
|
||||
{
|
||||
var sequencePoint =
|
||||
methodDebugDefinition.GetSequencePoints().OrderBy(s => s.StartLine).FirstOrDefault();
|
||||
var lineNumber = sequencePoint.StartLine;
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
private string GetMethodFileName(MethodDebugInformation methodDebugDefinition)
|
||||
{
|
||||
var fileName = string.Empty;
|
||||
if (!methodDebugDefinition.Document.IsNil)
|
||||
{
|
||||
var document = _reader.GetDocument(methodDebugDefinition.Document);
|
||||
fileName = _reader.GetString(document.Name);
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gcHandle.Free();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,38 +2,35 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using dia2;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public class SourceInformationProvider : ISourceInformationProvider
|
||||
{
|
||||
//private readonly IMetadataProjectReference _project;
|
||||
private readonly string _pdbPath;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPdbReader _pdbReader;
|
||||
|
||||
private bool? _isInitialized;
|
||||
private IDiaDataSource _diaDataSource;
|
||||
private IDiaSession _diaSession;
|
||||
private AssemblyData _assemblyData;
|
||||
|
||||
public SourceInformationProvider(
|
||||
string pdbPath,
|
||||
ILogger logger)
|
||||
public SourceInformationProvider(string pdbPath, ILogger logger) :
|
||||
this(pdbPath, logger, new PdbReaderFactory())
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(pdbPath) ||
|
||||
!File.Exists(pdbPath))
|
||||
}
|
||||
|
||||
public SourceInformationProvider(string pdbPath, ILogger logger, IPdbReaderFactory pdbReaderFactory)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pdbPath) || !File.Exists(pdbPath))
|
||||
{
|
||||
throw new ArgumentException($"The file '{pdbPath}' does not exist.", nameof(pdbPath));
|
||||
}
|
||||
|
||||
_pdbPath = pdbPath;
|
||||
_logger = logger;
|
||||
|
||||
_pdbReader = pdbReaderFactory.Create(pdbPath);
|
||||
}
|
||||
|
||||
public SourceInformation GetSourceInformation(MethodInfo method)
|
||||
|
@ -43,54 +40,31 @@ namespace Microsoft.Extensions.Testing.Abstractions
|
|||
throw new ArgumentNullException(nameof(method));
|
||||
}
|
||||
|
||||
if (!EnsureInitialized())
|
||||
{
|
||||
// Unable to load DIA or we had a failure reading the symbols.
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.Assert(_isInitialized == true);
|
||||
Debug.Assert(_diaSession != null);
|
||||
Debug.Assert(_assemblyData != null);
|
||||
|
||||
// We need a MethodInfo so we can deal with cases where no user code shows up for provided
|
||||
// method and class name. In particular:
|
||||
//
|
||||
// 1) inherited test methods (method.DeclaringType)
|
||||
// 2) async test methods (see StateMachineAttribute).
|
||||
// 2) async test methods (see StateMachineAttribute).t.
|
||||
//
|
||||
// Note that this doesn't deal gracefully with overloaded methods. Symbol APIs don't provide
|
||||
// a way to match overloads. We'd really need MetadataTokens to do this correctly (missing in
|
||||
// CoreCLR).
|
||||
method = ResolveBestMethodInfo(method);
|
||||
|
||||
var className = method.DeclaringType.FullName;
|
||||
var methodName = method.Name;
|
||||
|
||||
// The DIA code doesn't include a + for nested classes, just a dot.
|
||||
var symbolId = FindMethodSymbolId(className.Replace('+', '.'), methodName);
|
||||
if (symbolId == null)
|
||||
{
|
||||
// No matching method in the symbol.
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return GetSourceInformation(symbolId.Value);
|
||||
return _pdbReader.GetSourceInformation(method);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Failed to access source information in symbol.", ex);
|
||||
_logger?.LogWarning("Failed to access source information in symbol.", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private MethodInfo ResolveBestMethodInfo(MethodInfo method)
|
||||
{
|
||||
Debug.Assert(_isInitialized == true);
|
||||
|
||||
// If a method has a StateMachineAttribute, then all of the user code will show up
|
||||
// If a method has a StateMachineAttribute, then all of the user code will show up
|
||||
// in the symbols associated with the compiler-generated code. So, we need to look
|
||||
// for the 'MoveNext' on the generated type and resolve symbols for that.
|
||||
var attribute = method.GetCustomAttribute<StateMachineAttribute>();
|
||||
|
@ -104,212 +78,9 @@ namespace Microsoft.Extensions.Testing.Abstractions
|
|||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
private uint? FindMethodSymbolId(string className, string methodName)
|
||||
public void Dispose()
|
||||
{
|
||||
Debug.Assert(_isInitialized == true);
|
||||
|
||||
ClassData classData;
|
||||
if (_assemblyData.Classes.TryGetValue(className, out classData))
|
||||
{
|
||||
MethodData methodData;
|
||||
if (classData.Methods.TryGetValue(methodName, out methodData))
|
||||
{
|
||||
return methodData.SymbolId;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SourceInformation GetSourceInformation(uint symbolId)
|
||||
{
|
||||
Debug.Assert(_isInitialized == true);
|
||||
|
||||
string filename = null;
|
||||
int? lineNumber = null;
|
||||
|
||||
IDiaSymbol diaSymbol;
|
||||
_diaSession.symbolById(symbolId, out diaSymbol);
|
||||
if (diaSymbol == null)
|
||||
{
|
||||
// Doesn't seem like this should happen, since DIA gave us the id.
|
||||
return null;
|
||||
}
|
||||
|
||||
IDiaEnumLineNumbers diaLineNumbers;
|
||||
_diaSession.findLinesByAddr(
|
||||
diaSymbol.addressSection,
|
||||
diaSymbol.addressOffset,
|
||||
(uint)diaSymbol.length,
|
||||
out diaLineNumbers);
|
||||
|
||||
// Resist the user to use foreach here. It doesn't work well with these APIs.
|
||||
IDiaLineNumber diaLineNumber;
|
||||
var lineNumbersFetched = 0u;
|
||||
|
||||
diaLineNumbers.Next(1u, out diaLineNumber, out lineNumbersFetched);
|
||||
while (lineNumbersFetched == 1 && diaLineNumber != null)
|
||||
{
|
||||
if (filename == null)
|
||||
{
|
||||
var diaFile = diaLineNumber.sourceFile;
|
||||
if (diaFile != null)
|
||||
{
|
||||
filename = diaFile.fileName;
|
||||
}
|
||||
}
|
||||
|
||||
if (diaLineNumber.lineNumber != 16707566u)
|
||||
{
|
||||
// We'll see multiple line numbers for the same method, but we just want the first one.
|
||||
lineNumber = Math.Min(lineNumber ?? Int32.MaxValue, (int)diaLineNumber.lineNumber);
|
||||
}
|
||||
|
||||
diaLineNumbers.Next(1u, out diaLineNumber, out lineNumbersFetched);
|
||||
}
|
||||
|
||||
if (filename == null || lineNumber == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SourceInformation(filename, lineNumber.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool EnsureInitialized()
|
||||
{
|
||||
if (_isInitialized.HasValue)
|
||||
{
|
||||
return _isInitialized.Value;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_diaDataSource = (IDiaDataSource)new DiaDataSource();
|
||||
_isInitialized = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Failed to create DIA DataSource. No source information will be available.", ex);
|
||||
_isInitialized = false;
|
||||
return _isInitialized.Value;
|
||||
}
|
||||
|
||||
// We have a project, and we successfully loaded DIA, so let's capture the symbols
|
||||
// and create a session.
|
||||
try
|
||||
{
|
||||
_diaDataSource.loadDataFromPdb(_pdbPath);
|
||||
_diaDataSource.openSession(out _diaSession);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Failed to load symbols. No source information will be available.", ex);
|
||||
_isInitialized = false;
|
||||
return _isInitialized.Value;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_assemblyData = FetchSymbolData(_diaSession);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Failed to read symbols. No source information will be available.", ex);
|
||||
_isInitialized = false;
|
||||
return _isInitialized.Value;
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
return _isInitialized.Value;
|
||||
}
|
||||
|
||||
// Builds a lookup table of class+method name.
|
||||
//
|
||||
// It's easier to build it at once by enumerating, once we have the table, we
|
||||
// can use the symbolIds to look up the sources when we need them.
|
||||
private static AssemblyData FetchSymbolData(IDiaSession session)
|
||||
{
|
||||
// This will be a *flat* enumerator of all classes.
|
||||
//
|
||||
// A nested class will not contain a '+' in it's name, just a '.' separating the parent class name from
|
||||
// the child class name.
|
||||
IDiaEnumSymbols diaClasses;
|
||||
|
||||
session.findChildren(
|
||||
session.globalScope, // Search at the top-level.
|
||||
SymTagEnum.SymTagCompiland, // Just find classes.
|
||||
name: null, // Don't filter by name.
|
||||
compareFlags: 0u, // doesn't matter because name is null.
|
||||
ppResult: out diaClasses);
|
||||
|
||||
var assemblyData = new AssemblyData();
|
||||
|
||||
// Resist the urge to use foreach here. It doesn't work well with these APIs.
|
||||
var classesFetched = 0u;
|
||||
IDiaSymbol diaClass;
|
||||
|
||||
diaClasses.Next(1u, out diaClass, out classesFetched);
|
||||
while (classesFetched == 1 && diaClass != null)
|
||||
{
|
||||
var classData = new ClassData()
|
||||
{
|
||||
Name = diaClass.name,
|
||||
SymbolId = diaClass.symIndexId,
|
||||
};
|
||||
assemblyData.Classes.Add(diaClass.name, classData);
|
||||
|
||||
IDiaEnumSymbols diaMethods;
|
||||
session.findChildren(
|
||||
diaClass,
|
||||
SymTagEnum.SymTagFunction,
|
||||
name: null, // Don't filter by name.
|
||||
compareFlags: 0u, // doesn't matter because name is null.
|
||||
ppResult: out diaMethods);
|
||||
|
||||
// Resist the urge to use foreach here. It doesn't work well with these APIs.
|
||||
var methodsFetched = 0u;
|
||||
IDiaSymbol diaMethod;
|
||||
|
||||
diaMethods.Next(1u, out diaMethod, out methodsFetched);
|
||||
while (methodsFetched == 1 && diaMethod != null)
|
||||
{
|
||||
classData.Methods[diaMethod.name] = new MethodData()
|
||||
{
|
||||
Name = diaMethod.name,
|
||||
SymbolId = diaMethod.symIndexId,
|
||||
};
|
||||
|
||||
diaMethods.Next(1u, out diaMethod, out methodsFetched);
|
||||
}
|
||||
|
||||
diaClasses.Next(1u, out diaClass, out classesFetched);
|
||||
}
|
||||
|
||||
return assemblyData;
|
||||
}
|
||||
|
||||
private class AssemblyData
|
||||
{
|
||||
public IDictionary<string, ClassData> Classes { get; } = new Dictionary<string, ClassData>();
|
||||
}
|
||||
|
||||
private class ClassData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public uint SymbolId { get; set; }
|
||||
|
||||
public IDictionary<string, MethodData> Methods { get; } = new Dictionary<string, MethodData>();
|
||||
}
|
||||
|
||||
private class MethodData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public uint SymbolId { get; set; }
|
||||
_pdbReader.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.DiaSymReader;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
internal static class SymUnmanagedReaderExtensions
|
||||
{
|
||||
internal const int E_FAIL = unchecked((int)0x80004005);
|
||||
internal const int E_NOTIMPL = unchecked((int)0x80004001);
|
||||
|
||||
private static readonly IntPtr s_ignoreIErrorInfo = new IntPtr(-1);
|
||||
private delegate int ItemsGetter<TEntity, TItem>(TEntity entity, int bufferLength, out int count, TItem[] buffer);
|
||||
|
||||
internal static void ThrowExceptionForHR(int hr)
|
||||
{
|
||||
// E_FAIL indicates "no info".
|
||||
// E_NOTIMPL indicates a lack of ISymUnmanagedReader support (in a particular implementation).
|
||||
if (hr < 0 && hr != E_FAIL && hr != E_NOTIMPL)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(hr, s_ignoreIErrorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
internal static SourceInformation GetSourceInformation(this ISymUnmanagedMethod method)
|
||||
{
|
||||
var sequencePoint = method.GetSequencePoints().OrderBy(s => s.StartLine).FirstOrDefault();
|
||||
var fileName = sequencePoint.Document.GetName();
|
||||
var lineNumber = sequencePoint.StartLine;
|
||||
|
||||
return new SourceInformation(fileName, lineNumber);
|
||||
}
|
||||
|
||||
internal static ImmutableArray<SymUnmanagedSequencePoint> GetSequencePoints(this ISymUnmanagedMethod method)
|
||||
{
|
||||
// NB: method.GetSequencePoints(0, out numAvailable, ...) always returns 0.
|
||||
int numAvailable;
|
||||
int hr = method.GetSequencePointCount(out numAvailable);
|
||||
SymUnmanagedReaderExtensions.ThrowExceptionForHR(hr);
|
||||
if (numAvailable == 0)
|
||||
{
|
||||
return ImmutableArray<SymUnmanagedSequencePoint>.Empty;
|
||||
}
|
||||
|
||||
int[] offsets = new int[numAvailable];
|
||||
ISymUnmanagedDocument[] documents = new ISymUnmanagedDocument[numAvailable];
|
||||
int[] startLines = new int[numAvailable];
|
||||
int[] startColumns = new int[numAvailable];
|
||||
int[] endLines = new int[numAvailable];
|
||||
int[] endColumns = new int[numAvailable];
|
||||
|
||||
int numRead;
|
||||
hr = method.GetSequencePoints(numAvailable, out numRead, offsets, documents, startLines, startColumns, endLines, endColumns);
|
||||
SymUnmanagedReaderExtensions.ThrowExceptionForHR(hr);
|
||||
if (numRead != numAvailable)
|
||||
{
|
||||
throw new InvalidOperationException($"Read only {numRead} of {numAvailable} sequence points.");
|
||||
}
|
||||
|
||||
var builder = ImmutableArray.CreateBuilder<SymUnmanagedSequencePoint>(numRead);
|
||||
for (int i = 0; i < numRead; i++)
|
||||
{
|
||||
builder.Add(new SymUnmanagedSequencePoint(
|
||||
offsets[i],
|
||||
documents[i],
|
||||
startLines[i],
|
||||
startColumns[i],
|
||||
endLines[i],
|
||||
endColumns[i]));
|
||||
}
|
||||
|
||||
return builder.ToImmutable();
|
||||
}
|
||||
|
||||
internal static string GetName(this ISymUnmanagedDocument document)
|
||||
{
|
||||
return ToString(GetItems(document,
|
||||
(ISymUnmanagedDocument a, int b, out int c, char[] d) => a.GetUrl(b, out c, d)));
|
||||
}
|
||||
|
||||
private static TItem[] GetItems<TEntity, TItem>(TEntity entity, ItemsGetter<TEntity, TItem> getter)
|
||||
{
|
||||
int count;
|
||||
int hr = getter(entity, 0, out count, null);
|
||||
ThrowExceptionForHR(hr);
|
||||
if (count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = new TItem[count];
|
||||
hr = getter(entity, count, out count, result);
|
||||
ThrowExceptionForHR(hr);
|
||||
ValidateItems(count, result.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void ValidateItems(int actualCount, int bufferLength)
|
||||
{
|
||||
if (actualCount != bufferLength)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Read only {0} of {1} items.", actualCount, bufferLength));
|
||||
}
|
||||
}
|
||||
|
||||
private static string ToString(char[] buffer)
|
||||
{
|
||||
return new string(buffer, 0, buffer.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,17 +7,20 @@
|
|||
},
|
||||
"compilationOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"allowUnsafe": true,
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "7.0.1",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-rc2-16040"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-rc2-16040",
|
||||
"Microsoft.DiaSymReader": "1.0.6",
|
||||
"Microsoft.DiaSymReader.Native": "1.3.3"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
"netstandard1.5": {
|
||||
"imports": "dnxcore50",
|
||||
"imports": [ "dnxcore50", "portable-net45+win8" ],
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-23924",
|
||||
"System.Resources.ResourceManager": "4.0.1-rc2-23924",
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using TestAppWithFullPdbs;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions.Tests
|
||||
{
|
||||
public class GivenThatIWantToUseFullPdbsToFindMethodInformation
|
||||
{
|
||||
public FullPdbReader _pdbReader;
|
||||
|
||||
public GivenThatIWantToUseFullPdbsToFindMethodInformation()
|
||||
{
|
||||
var stream = new FileStream(
|
||||
Path.Combine(AppContext.BaseDirectory, "TestAppWithFullPdbs.pdb"),
|
||||
FileMode.Open,
|
||||
FileAccess.Read);
|
||||
_pdbReader = new FullPdbReader(stream);
|
||||
}
|
||||
|
||||
[WindowsOnlyFact]
|
||||
public void It_returns_the_right_file_and_the_right_file_number_when_the_method_exists_in_the_pdb()
|
||||
{
|
||||
var type = typeof(ClassForFullPdbs);
|
||||
var methodInfo = type.GetMethod("TestMethodForFullPdbs");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(methodInfo);
|
||||
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForFullPdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(6);
|
||||
}
|
||||
|
||||
[WindowsOnlyFact]
|
||||
public void It_returns_null_when_MethodInfo_is_null()
|
||||
{
|
||||
var type = typeof(ClassForFullPdbs);
|
||||
var methodInfo = type.GetMethod("Name_of_a_test_that_does_not_exist");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(methodInfo);
|
||||
|
||||
sourceInformation.Should().BeNull();
|
||||
}
|
||||
|
||||
[WindowsOnlyFact]
|
||||
public void It_returns_null_when_the_method_does_not_exist_in_the_pdb()
|
||||
{
|
||||
var type = typeof(PortablePdbReader);
|
||||
var methodInfo = type.GetMethod("GetSourceInformation");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(methodInfo);
|
||||
|
||||
sourceInformation.Should().BeNull();
|
||||
}
|
||||
|
||||
[WindowsOnlyFact]
|
||||
public void It_allows_us_to_invoke_GetSourceInformation_multiple_times()
|
||||
{
|
||||
var type = typeof(ClassForFullPdbs);
|
||||
var firstMethodInfo = type.GetMethod("TestMethodForFullPdbs");
|
||||
var secondMethodInfo = type.GetMethod("AnotherTestMethodForFullPdbs");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(secondMethodInfo);
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForFullPdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(10);
|
||||
|
||||
sourceInformation = _pdbReader.GetSourceInformation(firstMethodInfo);
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForFullPdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(6);
|
||||
|
||||
sourceInformation = _pdbReader.GetSourceInformation(secondMethodInfo);
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForFullPdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(10);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
using Microsoft.Extensions.Testing.Abstractions;
|
||||
using System.Reflection;
|
||||
using FluentAssertions;
|
||||
using TestAppWithPortablePdbs;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions.Tests
|
||||
{
|
||||
public class GivenThatIWantToUsePortablePdbsToFindMethodInformation
|
||||
{
|
||||
private PortablePdbReader _pdbReader;
|
||||
|
||||
public GivenThatIWantToUsePortablePdbsToFindMethodInformation()
|
||||
{
|
||||
var stream = new FileStream(
|
||||
Path.Combine(AppContext.BaseDirectory, "TestAppWithPortablePdbs.pdb"),
|
||||
FileMode.Open,
|
||||
FileAccess.Read);
|
||||
_pdbReader = new PortablePdbReader(stream);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_returns_the_right_file_and_the_right_file_number_when_the_method_exists_in_the_pdb()
|
||||
{
|
||||
var type = typeof (ClassForPortablePdbs);
|
||||
var methodInfo = type.GetMethod("TestMethodForPortablePdbs");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(methodInfo);
|
||||
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForPortablePdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(6);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_returns_null_when_MethodInfo_is_null()
|
||||
{
|
||||
var type = typeof(ClassForPortablePdbs);
|
||||
var methodInfo = type.GetMethod("Name_of_a_test_that_does_not_exist");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(methodInfo);
|
||||
|
||||
sourceInformation.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_returns_null_when_the_method_does_not_exist_in_the_pdb()
|
||||
{
|
||||
var type = typeof(PortablePdbReader);
|
||||
var methodInfo = type.GetMethod("GetSourceInformation");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(methodInfo);
|
||||
|
||||
sourceInformation.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_allows_us_to_invoke_GetSourceInformation_multiple_times()
|
||||
{
|
||||
var type = typeof(ClassForPortablePdbs);
|
||||
var firstMethodInfo = type.GetMethod("TestMethodForPortablePdbs");
|
||||
var secondMethodInfo = type.GetMethod("AnotherTestMethodForPortablePdbs");
|
||||
|
||||
var sourceInformation = _pdbReader.GetSourceInformation(secondMethodInfo);
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForPortablePdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(10);
|
||||
|
||||
sourceInformation = _pdbReader.GetSourceInformation(firstMethodInfo);
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForPortablePdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(6);
|
||||
|
||||
sourceInformation = _pdbReader.GetSourceInformation(secondMethodInfo);
|
||||
sourceInformation.Should().NotBeNull();
|
||||
sourceInformation.Filename.Should().Contain("ClassForPortablePdbs.cs");
|
||||
sourceInformation.LineNumber.Should().Be(10);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>09c61bd7-c6db-4f89-85bf-4eb3c196049d</ProjectGuid>
|
||||
<RootNamespace>Microsoft.Extensions.Testing.Abstractions.Tests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-23924",
|
||||
"Microsoft.Extensions.Testing.Abstractions": { "target": "project" },
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23924",
|
||||
"Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" },
|
||||
"TestAppWithFullPdbs": { "target": "project" },
|
||||
"TestAppWithPortablePdbs": { "target": "project" },
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-dev-91790-12",
|
||||
"FluentAssertions": "4.2.2"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandardapp1.5": {
|
||||
"imports": [
|
||||
"dnxcore50",
|
||||
"netstandard1.3",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"testRunner": "xunit"
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Testing.Abstractions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using System.Reflection;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions.UnitTests
|
||||
{
|
||||
public class GivenThatWeWantToUseSourceInformationProviderToGetSourceInformation
|
||||
{
|
||||
private string _pdbPath = Path.Combine(AppContext.BaseDirectory, "TestAppWithPortablePdbs.pdb");
|
||||
|
||||
[Fact]
|
||||
public void It_creates_a_pdb_reader_right_away()
|
||||
{
|
||||
var pdbReaderFactoryMock = new Mock<IPdbReaderFactory>();
|
||||
var sourceInformationProvider = new SourceInformationProvider(_pdbPath, null, pdbReaderFactoryMock.Object);
|
||||
|
||||
pdbReaderFactoryMock.Verify(p => p.Create(_pdbPath), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_uses_the_reader_to_get_the_SourceInformation()
|
||||
{
|
||||
var type = typeof(GivenThatWeWantToUseSourceInformationProviderToGetSourceInformation);
|
||||
var methodInfo = type.GetMethod("It_uses_the_reader_to_get_the_SourceInformation");
|
||||
|
||||
var expectedSourceInformation = new SourceInformation("some file path.cs", 12);
|
||||
var pdbReaderMock = new Mock<IPdbReader>();
|
||||
pdbReaderMock.Setup(p => p.GetSourceInformation(methodInfo)).Returns(expectedSourceInformation);
|
||||
|
||||
var pdbReaderFactoryMock = new Mock<IPdbReaderFactory>();
|
||||
pdbReaderFactoryMock.Setup(p => p.Create(_pdbPath)).Returns(pdbReaderMock.Object);
|
||||
|
||||
var sourceInformationProvider = new SourceInformationProvider(_pdbPath, null, pdbReaderFactoryMock.Object);
|
||||
|
||||
var actualSourceInformation = sourceInformationProvider.GetSourceInformation(methodInfo);
|
||||
|
||||
actualSourceInformation.Should().Be(expectedSourceInformation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_disposes_of_the_reader_when_it_gets_disposed()
|
||||
{
|
||||
var pdbReaderMock = new Mock<IPdbReader>();
|
||||
|
||||
var pdbReaderFactoryMock = new Mock<IPdbReaderFactory>();
|
||||
pdbReaderFactoryMock.Setup(p => p.Create(_pdbPath)).Returns(pdbReaderMock.Object);
|
||||
|
||||
using (var sourceInformationProvider =
|
||||
new SourceInformationProvider(_pdbPath, null, pdbReaderFactoryMock.Object))
|
||||
{
|
||||
}
|
||||
|
||||
pdbReaderMock.Verify(p => p.Dispose(), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>deb3ab06-fcd8-4119-b8ca-b7aa6ce2f22d</ProjectGuid>
|
||||
<RootNamespace>Microsoft.Extensions.Testing.Abstractions.UnitTests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-23924",
|
||||
"Microsoft.Extensions.Testing.Abstractions": { "target": "project" },
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23924",
|
||||
"System.Diagnostics.Process": "4.1.0-rc2-23924",
|
||||
"TestAppWithPortablePdbs": { "target": "project" },
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-dev-91790-12",
|
||||
"FluentAssertions": "4.2.2",
|
||||
"moq.netcore": "4.4.0-beta8"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandardapp1.5": {
|
||||
"imports": [
|
||||
"dnxcore50",
|
||||
"netstandard1.3",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"testRunner": "xunit"
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace TestAppWithFullPdbs
|
||||
{
|
||||
public class ClassForFullPdbs
|
||||
{
|
||||
public void TestMethodForFullPdbs()
|
||||
{
|
||||
}
|
||||
|
||||
public void AnotherTestMethodForFullPdbs()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0.25029" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>0a37ab59-bdb5-4957-9bb8-d965f9a67a5b</ProjectGuid>
|
||||
<RootNamespace>TestAppWithFullPdbs</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
14
test/TestingAbstractions/TestAppWithFullPdbs/project.json
Normal file
14
test/TestingAbstractions/TestAppWithFullPdbs/project.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"compilationOptions": {
|
||||
"debugType": "full"
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-23924"
|
||||
},
|
||||
"frameworks": {
|
||||
"netstandard1.5": {
|
||||
"imports": [ "portable-net45+win8", "dnxcore50" ]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace TestAppWithPortablePdbs
|
||||
{
|
||||
public class ClassForPortablePdbs
|
||||
{
|
||||
public void TestMethodForPortablePdbs()
|
||||
{
|
||||
}
|
||||
|
||||
public void AnotherTestMethodForPortablePdbs()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0.25029" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>7b0efbb4-4669-4b83-b47c-7f3e6db07af9</ProjectGuid>
|
||||
<RootNamespace>TestAppWithPortablePdbs</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"compilationOptions": {
|
||||
"debugType": "portable"
|
||||
},
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-23924"
|
||||
},
|
||||
"frameworks": {
|
||||
"netstandard1.5": {
|
||||
"imports": [ "portable-net45+win8", "dnxcore50" ]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.23107</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
|
|||
public void It_builds_the_project_using_the_output_passed()
|
||||
{
|
||||
var testCommand = new DotnetTestCommand();
|
||||
var result = testCommand.Execute($"{_projectFilePath} -o {AppContext.BaseDirectory} -f netstandardapp1.5");
|
||||
var result = testCommand.Execute(
|
||||
$"{_projectFilePath} -o {Path.Combine(AppContext.BaseDirectory, "output")} -f netstandardapp1.5");
|
||||
result.Should().Pass();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
"Microsoft.DotNet.ProjectModel": {
|
||||
"target": "project"
|
||||
},
|
||||
"Microsoft.Extensions.Testing.Abstractions": {
|
||||
"target": "project"
|
||||
},
|
||||
"System.Net.NameResolution": "4.0.0-rc2-23924",
|
||||
"System.Net.Sockets": "4.1.0-rc2-23924",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23924",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<ProjectGuid>efc4fe68-83eb-40e4-bfa8-61d0b4626f25</ProjectGuid>
|
||||
<RootNamespace>RuntimeGraphGenerator</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
Loading…
Reference in a new issue