System.AppDomain으로부터 .NET Profiler의 AppDomainID 구하는 방법
.NET Profiler의 AppDomainCreationFinished 콜백에는 AppDomainID 값이 있습니다.
ICorProfilerCallback::AppDomainCreationFinished Method
; https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilercallback-appdomaincreationfinished-method
이 값 역시 메모리 상의 위치 값이며 실행 시마다 변경되는데, 당연히 System.AppDomain 타입의 Id 속성값과는 별개의 값입니다.
그렇다면 어떻게 Managed 환경의 AppDomain.CurrentDomain과 .NET Profiler의 AppDomainID 값을 연관시킬 수 있을까요? 우선, AppDomain 타입의 경우 공식적으로 이에 대한 값을 제공하지 않습니다.
단지, private 필드로 2.0에서는 _dummyField라는 이름으로, 4.0에서는 _pDomain이라는 이름으로 보유하고 있는데 따라서 Reflection을 통해 이 값들을 접근해 AppDomainID 값을 구할 수는 있습니다.
using System;
using System.Reflection;
class Program
{
static unsafe void Main(string[] args)
{
long result = GetCurrentAppDomainID();
Console.WriteLine(result);
}
private static long GetCurrentAppDomainID()
{
Type domainType = typeof(AppDomain);
long id = TryGetAppDomainId(domainType, "_dummyField");
if (id == 0)
{
id = TryGetAppDomainId(domainType, "_pDomain");
}
return id;
}
static private long TryGetAppDomainId(Type domainType, string fieldName)
{
try
{
FieldInfo field = domainType.GetField(fieldName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (field == null)
{
return 0;
}
object objValue = field.GetValue(AppDomain.CurrentDomain);
if (objValue == null)
{
return 0;
}
return ((IntPtr)objValue).ToInt64();
}
catch { }
return 0;
}
}
private 필드를 접근하는 것이 찜찜하죠? ^^ 다행히 더 좋은 방법이 있습니다. 어차피 .NET Profiler DLL 모듈과 연동하기 위해 AppDomainID가 필요한 것이므로 Profiler DLL에게 물어보면 됩니다. 그리고 DLL 측에서는 다음의 메서드들을 이용해 AppDomainID 값을 반환해 주면 됩니다.
ICorProfilerInfo::GetCurrentThreadID Method
; https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilerinfo-getcurrentthreadid-method
ICorProfilerInfo2::GetThreadAppDomain Method
; https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/icorprofilerinfo2-getthreadappdomain-method
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]