private static void Main(string[] args) { MDbgProcess proc = null; try { int processId = Int32.Parse(args[0]); MDbgEngine debugger = new MDbgEngine(); proc = debugger.Attach(processId); InitializeMdbg(debugger, proc); DumpThreads(proc); } catch { PrintUsage(); } finally { if (proc != null) { // We always want to detach from target. proc.Detach().WaitOne(); } } }
private void Cleanup() { MDbgProcess active = Debugger.Processes.Active; active.Breakpoints.DeleteAll(); active.CorProcess.Stop(0); active.Detach(); }
/// <summary> /// 利用VS调试工具输出线程堆栈测试 http://blogs.msdn.com/b/jmstall/archive/2005/11/28/snapshot.aspx /// </summary> /// <param name="args"></param> static void Main(string[] args) { do { Console.WriteLine("pid?"); int pid; if (!int.TryParse(Console.ReadLine(), out pid)) { return; } MDbgEngine debugger = new MDbgEngine(); MDbgProcess proc = null; try { proc = debugger.Attach(pid); DrainAttach(debugger, proc); MDbgThreadCollection tc = proc.Threads; Console.WriteLine("Attached to pid:{0}", pid); foreach (MDbgThread t in tc) { Console.WriteLine("Callstack for Thread {0}", t.Id.ToString()); foreach (MDbgFrame f in t.Frames) { Console.WriteLine(" " + f); } } } finally { if (proc != null) { proc.Detach().WaitOne(); } } }while (true); }
protected virtual void Dispose(bool disposing) { // 防止被多次调用 if (disposed) { return; } if (disposing) { // 清除所有托管资源 if (_mdbgProcess != null) { // 确保基本进程在datach前已经终止了 var waithandler = _mdbgProcess.AsyncStop(); waithandler.WaitOne(); _mdbgProcess.Detach(); } } disposed = true; }
protected virtual void Dispose(bool disposing) { // Protect from being called multiple times. if (disposed) { return; } if (disposing) { // Clean up all managed resources. if (_mdbgProcess != null) { // Make sure the underlying CorProcess was stopped before // detached it. var waithandler = _mdbgProcess.AsyncStop(); waithandler.WaitOne(); _mdbgProcess.Detach(); } } disposed = true; }
// Expects 1 arg, the pid as a decimal string private static void Main(string[] args) { try { int pid = int.Parse(args[0]); var sb = new StringBuilder(); Process process = Process.GetProcessById(pid); //var counters = new Dictionary<string, MyThreadCounterInfo>(); //var threadInfos = new Dictionary<string, MyThreadInfo>(); ////zhanggangb //sb.AppendFormat( // @"<html><head><title>{0}</title><style type=""text/css"">table, td{{border: 1px solid #000;border-collapse: collapse;}}</style></head><body>", // process.ProcessName); //Console.WriteLine("1、正在收集计数器:"); //var cate = new PerformanceCounterCategory("Thread"); //string[] instances = cate.GetInstanceNames(); //foreach (string instance in instances) //{ // if (instance.StartsWith(process.ProcessName, StringComparison.CurrentCultureIgnoreCase)) // { // var counter1 = // new PerformanceCounter("Thread", "ID Thread", instance, true); // var counter2 = // new PerformanceCounter("Thread", "% Processor Time", instance, true); // counters.Add(instance, new MyThreadCounterInfo(counter1, counter2)); // } //} //foreach (var pair in counters) //{ // try // { // pair.Value.IdCounter.NextValue(); // pair.Value.ProcessorTimeCounter.NextValue(); // } // catch(Exception ex) // { // Console.WriteLine(ex.Message); // } //} //Thread.Sleep(5000); //foreach (var pair in counters) //{ // try // { // var info = new MyThreadInfo(); // info.Id = pair.Value.IdCounter.NextValue().ToString(); // info.ProcessorTimePercentage = pair.Value.ProcessorTimeCounter.NextValue().ToString("0.0"); // threadInfos.Add(info.Id, info); // } // catch(Exception ex) // { // Console.WriteLine(ex.Message); // } //} //Console.WriteLine("2、正在收集线程信息"); //ProcessThreadCollection collection = process.Threads; //foreach (ProcessThread thread in collection) //{ // try // { // MyThreadInfo info; // if (threadInfos.TryGetValue(thread.Id.ToString(), out info)) // { // info.UserProcessorTime = thread.UserProcessorTime.ToString(); // info.StartTime = thread.StartTime.ToString(); // } // } // catch (Exception ex) // { // Console.WriteLine(ex.Message); // } //} var debugger = new MDbgEngine(); debugger.Options.StopOnException = true; StringBuilder sbb = new StringBuilder(); MDbgProcess proc = null; try { proc = debugger.Attach(pid); DrainAttach(debugger, proc); var tc = proc.Threads; Console.WriteLine("3、正在附加到进程{0}获取调用栈", pid); foreach (MDbgThread t in tc) { var tempStrs = new StringBuilder(); foreach (MDbgFrame f in t.Frames) { tempStrs.AppendFormat("<br />" + f); } MyThreadInfo info; if (threadInfos.TryGetValue(t.Id.ToString(), out info)) { info.CallStack = tempStrs.Length == 0 ? "no managment call stack" : tempStrs.ToString(); sb.Append(info.CallStack); } } } finally { if (proc != null) { proc.Detach().WaitOne(); } } Console.WriteLine("4、正在生成报表"); using (var sw = new StreamWriter(@"D:\View\MYBLOG\CpuAnalyzer\bin\Debug\" + process.Id + ".htm", false, Encoding.Default)) { sw.Write(sbb.ToString()); } //按照cpu占用率排序 //var result = threadInfos.Values.ToArray().OrderByDescending(item => double.Parse(item.ProcessorTimePercentage)); //foreach (var info in result) //{ // sb.Append(info.ToString()); // sb.Append("<hr />"); //} //sb.Append("</body></html>"); //Console.WriteLine("4、正在生成报表"); //using (var sw = new StreamWriter(@"D:\View\MYBLOG\CpuAnalyzer\bin\Debug\"+process.Id + ".htm", false, // Encoding.Default)) //{ // sw.Write(sb.ToString()); //} Process.Start(@"D:\View\MYBLOG\CpuAnalyzer\bin\Debug\" + process.Id + ".htm"); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("分析结束"); Console.ReadKey(); }
static void Main(string[] args) { if (args.Length < 1) { Usage(); return; } int samples = 10; int sampleInterval = 1000; var state = ParseState.Unknown; foreach (var arg in args.Skip(1)) { switch (state) { case ParseState.Unknown: if (arg.ToLower() == "/s") { state = ParseState.Samples; } else if (arg.ToLower() == "/i") { state = ParseState.Interval; } else { Usage(); return; } break; case ParseState.Samples: if (!Int32.TryParse(arg, out samples)) { Usage(); return; } state = ParseState.Unknown; break; case ParseState.Interval: if (!Int32.TryParse(arg, out sampleInterval)) { Usage(); return; } state = ParseState.Unknown; break; default: break; } } string pidOrProcess = args[0]; var stats = new Dictionary <int, List <ThreadSnapshot> >(); var debugger = new MDbgEngine(); int pid = -1; var processes = Process.GetProcessesByName(pidOrProcess); if (processes.Length < 1) { try { pid = Int32.Parse(pidOrProcess); } catch { Console.WriteLine("Error: could not find any processes with that name or pid"); return; } } else { if (processes.Length > 1) { Console.WriteLine("Warning: multiple processes share that name, attaching to the first"); } pid = processes[0].Id; } MDbgProcess attached = null; try { attached = debugger.Attach(pid); } catch (Exception e) { Console.WriteLine("Error: failed to attach to process: " + e); return; } attached.Go().WaitOne(); for (int i = 0; i < samples; i++) { foreach (MDbgThread thread in attached.Threads) { var snapshot = ThreadSnapshot.GetThreadSnapshot(thread); List <ThreadSnapshot> snapshots; if (!stats.TryGetValue(snapshot.Id, out snapshots)) { snapshots = new List <ThreadSnapshot>(); stats[snapshot.Id] = snapshots; } snapshots.Add(snapshot); } attached.Go(); Thread.Sleep(sampleInterval); attached.AsyncStop().WaitOne(); } attached.Detach().WaitOne(); // perform basic analysis to see which are the top N stack traces observed, // weighted on cost Dictionary <Guid, long> costs = new Dictionary <Guid, long>(); Dictionary <Guid, string> stacks = new Dictionary <Guid, string>(); foreach (var stat in stats.Values) { long prevTime = -1; foreach (var snapshot in stat) { long time = snapshot.KernelTime + snapshot.UserTime; if (prevTime != -1) { foreach (var tuple in snapshot.StackHashes) { if (costs.ContainsKey(tuple.Item1)) { costs[tuple.Item1] += time - prevTime; } else { costs[tuple.Item1] = time - prevTime; stacks[tuple.Item1] = tuple.Item2; } } } prevTime = time; } } Console.WriteLine("Most expensive stacks"); Console.WriteLine("------------------------------------"); foreach (var group in costs.OrderByDescending(p => p.Value).GroupBy(p => p.Value)) { List <string> stacksToShow = new List <string>(); foreach (var pair in group.OrderByDescending(p => stacks[p.Key].Length)) { if (!stacksToShow.Any(s => s.Contains(stacks[pair.Key]))) { stacksToShow.Add(stacks[pair.Key]); } } foreach (var stack in stacksToShow) { Console.WriteLine(stack); Console.WriteLine("===> Cost ({0})", group.Key); Console.WriteLine(); } } var offenders = stats.Values .Select(_ => ThreadSnapshotStats.FromSnapshots(_)) .OrderBy(stat => stat.TotalKernelTime + stat.TotalUserTime) .Reverse(); foreach (var stat in offenders) { Console.WriteLine("------------------------------------"); Console.WriteLine(stat.ThreadId); Console.WriteLine("Kernel: {0} User: {1}", stat.TotalKernelTime, stat.TotalUserTime); foreach (var method in stat.CommonStack) { Console.WriteLine(method); } Console.WriteLine("Other Stacks:"); var prev = new List <string>(); foreach (var trace in stats[stat.ThreadId].Select(_ => _.StackTrace)) { if (!prev.SequenceEqual(trace)) { Console.WriteLine(); foreach (var method in trace) { Console.WriteLine(method); } } else { Console.WriteLine("<skipped>"); } prev = trace; } Console.WriteLine("------------------------------------"); } }
private void GetCurrentCallStack(Dictionary <string, ThreadCounterInfo> counters, Dictionary <string, ThreadOutputInfo> threadInfos) { var debugger = new MDbgEngine(); MDbgProcess proc = null; try { Console.WriteLine($"start attack to {PID} to get call stack"); proc = debugger.Attach((int)PID); DrainAttach(debugger, proc); Console.WriteLine($"had attacked to {PID}"); var counterThreadIDList = counters.Select(p => p.Value.ThreadID).ToList(); MDbgThreadCollection tc = proc.Threads; foreach (MDbgThread t in tc) { try { // 计数器没有的线程,不拿堆栈 if (!counterThreadIDList.Contains(t.Id.ToString())) { continue; } Console.WriteLine($"start get {t.Id}'s call stack"); var tempStrs = new StringBuilder(); foreach (MDbgFrame f in t.Frames) { tempStrs.AppendFormat("<br />" + f); } ThreadOutputInfo info; if (threadInfos.TryGetValue(t.Id.ToString(), out info)) { var stack = $"{DateTime.Now.ToString()}<br/>"; stack = stack + (tempStrs.Length == 0 ? "no managment call stack" : tempStrs.ToString()); info.CallStack.Add(stack); } Console.WriteLine($"had got {t.Id}'s call stack"); } catch (Exception ee) { WriteErrorLog("获取堆栈时出错:" + ee.ToString() + Environment.NewLine); Console.WriteLine($"an exception occur when got {t.Number}'s call stack, Log file {LogFile} for detail"); } } } catch (Exception ex) { WriteErrorLog("附加到进程时出错:" + ex.ToString() + Environment.NewLine); Console.WriteLine($"an exception occur when attack to process, Log file {LogFile} for detail"); } finally { if (proc != null) { proc.Detach().WaitOne(); } } }
// Expects 1 arg, the pid as a decimal string private static void Main(string[] args) { try { Console.WriteLine("请输入pid:"); int pid = int.Parse(Console.ReadLine()); var sb = new StringBuilder(); Process process = Process.GetProcessById(pid); var counters = new Dictionary <string, MyThreadCounterInfo>(); var threadInfos = new Dictionary <string, MyThreadInfo>(); sb.AppendFormat( @"<html><head><title>{0}</title><style type=""text/css"">table, td{{border: 1px solid #000;border-collapse: collapse;}}</style></head><body>", process.ProcessName); Console.WriteLine("1、正在收集计数器"); var cate = new PerformanceCounterCategory("Thread"); string[] instances = cate.GetInstanceNames(); foreach (string instance in instances) { if (instance.StartsWith(process.ProcessName, StringComparison.CurrentCultureIgnoreCase)) { var counter1 = new PerformanceCounter("Thread", "ID Thread", instance, true); var counter2 = new PerformanceCounter("Thread", "% Processor Time", instance, true); counters.Add(instance, new MyThreadCounterInfo(counter1, counter2)); } } foreach (var pair in counters) { try { pair.Value.IdCounter.NextValue(); pair.Value.ProcessorTimeCounter.NextValue(); } catch (Exception ex) { Console.WriteLine(ex); throw; } } Thread.Sleep(1000); foreach (var pair in counters) { try { var info = new MyThreadInfo(); info.Id = pair.Value.IdCounter.NextValue().ToString(); info.ProcessorTimePercentage = pair.Value.ProcessorTimeCounter.NextValue().ToString("0.0"); threadInfos.Add(info.Id, info); } catch { } } Console.WriteLine("2、正在收集线程信息"); ProcessThreadCollection collection = process.Threads; foreach (ProcessThread thread in collection) { try { MyThreadInfo info; if (threadInfos.TryGetValue(thread.Id.ToString(), out info)) { info.UserProcessorTime = thread.UserProcessorTime.ToString(); info.StartTime = thread.StartTime.ToString(); } } catch { } } var debugger = new MDbgEngine(); MDbgProcess proc = null; try { proc = debugger.Attach(pid); DrainAttach(debugger, proc); MDbgThreadCollection tc = proc.Threads; Console.WriteLine("3、正在附加到进程{0}获取调用栈", pid); foreach (MDbgThread t in tc) { var tempStrs = new StringBuilder(); foreach (MDbgFrame f in t.Frames) { tempStrs.AppendFormat("<br />" + f); } MyThreadInfo info; if (threadInfos.TryGetValue(t.Id.ToString(), out info)) { info.CallStack = tempStrs.Length == 0 ? "no managment call stack" : tempStrs.ToString(); } } } finally { if (proc != null) { proc.Detach().WaitOne(); } } foreach (var info in threadInfos) { sb.Append(info.Value.ToString()); sb.Append("<hr />"); } sb.Append("</body></html>"); Console.WriteLine("4、正在生成报表"); using (var sw = new StreamWriter(process.ProcessName + ".htm", false, Encoding.Default)) { sw.Write(sb.ToString()); } Process.Start(process.ProcessName + ".htm"); } catch (Exception ex) { Console.WriteLine(ex); } Console.WriteLine("运行完毕,按回车键关闭"); Console.ReadLine(); }
// Expects 1 arg, the pid as a decimal string public void Analyse(int pid) { try { var stopwt = new Stopwatch(); var sb = new StringBuilder(); var process = Process.GetProcessById(pid); var counters = new Dictionary <string, MyThreadCounterInfo>(); var threadInfos = new Dictionary <string, MyThreadInfo>(); sb.AppendFormat( @"<html><head><title>{0}</title><style type=""text/css"">table, td{{border: 1px solid #000;border-collapse: collapse;}}</style></head><body>", process.ProcessName); Console.WriteLine("1、正在收集计数器"); var cate = new PerformanceCounterCategory("Thread"); string[] instances = cate.GetInstanceNames(); Console.WriteLine("instances总数:{0}", instances.Length); stopwt.Start(); foreach (string instance in instances) { if (instance.StartsWith(process.ProcessName, StringComparison.CurrentCultureIgnoreCase)) { var counter1 = new PerformanceCounter("Thread", "ID Thread", instance, true); var counter2 = new PerformanceCounter("Thread", "% Processor Time", instance, true); counters.Add(instance, new MyThreadCounterInfo(counter1, counter2)); } } var i = 0; Console.WriteLine("counters总数:{0} {1}ms", counters.Count, stopwt.ElapsedMilliseconds); stopwt.Restart(); foreach (var pair in counters) { try { pair.Value.IdCounter.NextValue(); pair.Value.ProcessorTimeCounter.NextValue(); } catch (Exception ex) { Console.WriteLine("#{0} {1}", i, ex.Message); } i++; } Console.WriteLine("counters foreach {0}ms", stopwt.ElapsedMilliseconds); Thread.Sleep(5000); stopwt.Restart(); i = 0; foreach (var pair in counters) { try { var info = new MyThreadInfo(); info.Id = pair.Value.IdCounter.NextValue().ToString(); info.ProcessorTimePercentage = pair.Value.ProcessorTimeCounter.NextValue().ToString("0.0"); threadInfos.Add(info.Id, info); } catch (Exception ex) { Console.WriteLine("#{0} {1}", i, ex.Message); } i++; } i = 0; Console.WriteLine("counters foreach 2 {0}ms", stopwt.ElapsedMilliseconds); stopwt.Restart(); Console.WriteLine("2、正在收集线程信息"); ProcessThreadCollection collection = process.Threads; Console.WriteLine("Threads总数:{0}", collection.Count); foreach (ProcessThread thread in collection) { try { MyThreadInfo info; if (threadInfos.TryGetValue(thread.Id.ToString(), out info)) { info.UserProcessorTime = thread.UserProcessorTime.ToString(); info.StartTime = thread.StartTime.ToString(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } Console.WriteLine("完成收集线程信息 {0}ms", stopwt.ElapsedMilliseconds); stopwt.Restart(); var debugger = new MDbgEngine(); MDbgProcess proc = null; try { Console.WriteLine("3、正在附加到进程{0}获取调用栈", pid); proc = debugger.Attach(pid); DrainAttach(debugger, proc); var tc = proc.Threads; foreach (MDbgThread t in tc) { var tempStrs = new StringBuilder(); foreach (MDbgFrame f in t.Frames) { tempStrs.AppendFormat("<br />" + f); } MyThreadInfo info; if (threadInfos.TryGetValue(t.Id.ToString(), out info)) { info.CallStack = tempStrs.Length == 0 ? "no managment call stack" : tempStrs.ToString(); } } } finally { if (proc != null) { proc.Detach().WaitOne(); } } //修改成按照cpu占用率排序 var result = threadInfos.Values.ToArray().OrderByDescending(item => double.Parse(item.ProcessorTimePercentage)); Console.WriteLine("4、正在生成报表"); foreach (var info in result) { sb.Append(info.ToString()); sb.Append("<hr />"); } sb.Append("</body></html>"); using (var sw = new StreamWriter(process.ProcessName + ".htm", false, Encoding.Default)) { sw.Write(sb.ToString()); } Process.Start(process.ProcessName + ".htm"); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("分析结束"); //Console.ReadKey(); }
private void ExectueCmdForMdbg() { int pid = Process.GetCurrentProcess().Id; result = "内部调用栈测试!"; var sb = new StringBuilder(); Process process = Process.GetProcessById(pid); var counters = new Dictionary <string, MyThreadCounterInfo>(); var threadInfos = new Dictionary <string, MyThreadInfo>(); //sb.AppendFormat(@"<html><head><title>{0}</title><style type=""text/css"">table, td{{border: 1px solid #000;border-collapse: collapse;}}</style></head><body>",process.ProcessName); //收集计数器 var cate = new PerformanceCounterCategory("Thread"); string[] instances = cate.GetInstanceNames(); foreach (string instance in instances) { if (instance.StartsWith(process.ProcessName, StringComparison.CurrentCultureIgnoreCase)) { var counter1 = new PerformanceCounter("Thread", "ID Thread", instance, true); var counter2 = new PerformanceCounter("Thread", "% Processor Time", instance, true); counters.Add(instance, new MyThreadCounterInfo(counter1, counter2)); } } foreach (var pair in counters) { try { pair.Value.IdCounter.NextValue(); pair.Value.ProcessorTimeCounter.NextValue(); } catch (Exception ex) { //throw; //todo 写到日志 zhanggangb } } Thread.Sleep(5000); foreach (var pair in counters) { try { var info = new MyThreadInfo(); info.Id = pair.Value.IdCounter.NextValue().ToString(); info.ProcessorTimePercentage = pair.Value.ProcessorTimeCounter.NextValue().ToString("0.0"); threadInfos.Add(info.Id, info); } catch (Exception ex) { // throw; } } //收到线程信息 ProcessThreadCollection collection = process.Threads; foreach (ProcessThread thread in collection) { try { MyThreadInfo info; if (threadInfos.TryGetValue(thread.Id.ToString(), out info)) { info.UserProcessorTime = thread.Id.ToString(); info.StartTime = thread.StartTime.ToString(); } } catch (Exception) { //throw; } } var debugger = new MDbgEngine(); debugger.Options.StopOnException = true; MDbgProcess proc = null; try { proc = debugger.Attach(pid); DrainAttach(debugger, proc); var tc = proc.Threads; //附加到进程获取调用栈 foreach (MDbgThread t in tc) { var tempStrs = new StringBuilder(); foreach (MDbgFrame f in t.Frames) { tempStrs.AppendFormat("<br />" + f); } MyThreadInfo info; if (threadInfos.TryGetValue(t.Id.ToString(), out info)) { info.CallStack = tempStrs.Length == 0 ? "没有托管调用栈" : tempStrs.ToString(); } } } catch (Exception ex) { //throw; } finally { if (proc != null) { proc.Detach().WaitOne(); } } //按照CPU占用率排序 var threadresult = threadInfos.Values.ToArray().OrderByDescending(item => double.Parse(item.ProcessorTimePercentage)); foreach (var info in threadresult) { sb.Append(info.ToString()); sb.Append("<hr />"); } //sb.Append("</body></html>") //Utility.Logger.Log(message); //生成报表 //using (var sw = new StreamWriter(process.ProcessName+".html",false,Encoding.Default)) //{ // sw.Write(sb.ToString()); //} //process.Start(process.ProcessName + ".html"); result = sb.ToString(); }