-
-
Save zhangz/51582c5c956b4268de2c58285e29bd26 to your computer and use it in GitHub Desktop.
Code which enumerates appdomains in a remote process using ETW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Microsoft.Diagnostics.Tracing; | |
| using Microsoft.Diagnostics.Tracing.Session; | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Diagnostics; | |
| using System.Threading; | |
| namespace ClrDacManaged | |
| { | |
| class Program | |
| { | |
| private const ushort DCStartInitEventId = 147; | |
| private const ushort DCStartCompleteEventId = 145; | |
| private const ushort AppDomainDCStartEventId = 157; | |
| private readonly TimeSpan rundownTimeout = TimeSpan.FromSeconds(3); | |
| private readonly Dictionary<int, ICollection<AppDomainInfo>> processAppDomainsMap = new Dictionary<int, ICollection<AppDomainInfo>>(); | |
| private readonly int currentProcessId = Process.GetCurrentProcess().Id; | |
| private DateTime lastTimeEventWasReceivedUtc; | |
| private TraceEventSession session; | |
| private bool completed; | |
| public struct AppDomainInfo | |
| { | |
| public long Id; | |
| public string Name; | |
| } | |
| public void CollectAppDomainInfo() | |
| { | |
| Debug.Assert(!completed); | |
| using (session = new TraceEventSession("MusketeerEtwSession")) { | |
| session.Source.Dynamic.All += ProcessTraceEvent; | |
| session.EnableProvider("Microsoft-Windows-DotNETRuntimeRundown", TraceEventLevel.Verbose, | |
| 0x40L | // StartRundownKeyword | |
| 0x8L // LoaderRundownKeyword | |
| ); | |
| ThreadPool.QueueUserWorkItem(WatchDog); | |
| lastTimeEventWasReceivedUtc = DateTime.UtcNow; | |
| session.Source.Process(); | |
| } | |
| completed = true; | |
| } | |
| void WatchDog(object o) | |
| { | |
| while (true) { | |
| Thread.Sleep(TimeSpan.FromSeconds(1)); | |
| if (session.IsActive && DateTime.UtcNow.Subtract( | |
| lastTimeEventWasReceivedUtc) > rundownTimeout) { | |
| // rundown should be finished by now | |
| session.Stop(); | |
| break; | |
| } | |
| } | |
| } | |
| public void Stop() | |
| { | |
| if (session != null && session.IsActive) { | |
| session.Stop(); | |
| } | |
| } | |
| void ProcessTraceEvent(TraceEvent traceEvent) | |
| { | |
| lastTimeEventWasReceivedUtc = DateTime.UtcNow; | |
| if (traceEvent.ProcessID == currentProcessId) { | |
| return; | |
| } | |
| if ((ushort)traceEvent.ID == DCStartInitEventId) { | |
| Debug.Assert(!processAppDomainsMap.ContainsKey(traceEvent.ProcessID)); | |
| processAppDomainsMap.Add(traceEvent.ProcessID, new List<AppDomainInfo>()); | |
| } else if ((ushort)traceEvent.ID == AppDomainDCStartEventId) { | |
| Debug.Assert(processAppDomainsMap.ContainsKey(traceEvent.ProcessID)); | |
| processAppDomainsMap[traceEvent.ProcessID].Add(new AppDomainInfo() { | |
| Id = (long)traceEvent.PayloadByName("AppDomainID"), | |
| Name = (string)traceEvent.PayloadByName("AppDomainName") | |
| }); | |
| } | |
| } | |
| public IEnumerable<int> GetManagedProcessIds() | |
| { | |
| Debug.Assert(completed); | |
| return processAppDomainsMap.Keys; | |
| } | |
| public IEnumerable<AppDomainInfo> GetAppDomainsForProcess(int pid) | |
| { | |
| Debug.Assert(completed); | |
| ICollection<AppDomainInfo> appDomains; | |
| return processAppDomainsMap.TryGetValue(pid, out appDomains) ? appDomains : new AppDomainInfo[0]; | |
| } | |
| static void Main(string[] args) | |
| { | |
| var p = new Program(); | |
| Console.CancelKeyPress += (o, ev) => { | |
| p.Stop(); | |
| }; | |
| p.CollectAppDomainInfo(); | |
| foreach (var pid in p.GetManagedProcessIds()) { | |
| Console.WriteLine("### Managed process: {0} ###", pid); | |
| foreach (var appdomain in p.GetAppDomainsForProcess(pid)) { | |
| Console.WriteLine("==> AppDomain: {0} ({1})", appdomain.Name, appdomain.Id); | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment