วิธีการพิมพ์ Stack Trace ปัจจุบันใน. NET โดยไม่มีข้อยกเว้น?


350

ฉันมีรหัส C # ปกติ ผมไม่มีข้อยกเว้น ฉันต้องการบันทึกการติดตามสแต็กปัจจุบันโดยทางโปรแกรมเพื่อวัตถุประสงค์ในการดีบัก ตัวอย่าง:

public void executeMethod() 
{
    logStackTrace();
    method();
}

คำตอบ:


401

ดูSystem.Diagnosticsเนมสเปซ มีสินค้ามากมายในนั้น!

System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();

นี่เป็นเรื่องดีจริง ๆ ที่มีการกระตุ้นเพื่อเรียนรู้สิ่งที่เกิดขึ้นภายใต้ประทุน

ฉันขอแนะนำให้คุณดูที่วิธีแก้ไขปัญหาการเข้าสู่ระบบ (เช่น NLog, log4net หรือรูปแบบและแนวทางปฏิบัติของ Microsoft Enterprise Library) ซึ่งอาจบรรลุวัตถุประสงค์ของคุณ ขอให้โชคดี


74
โปรดจำไว้ว่าสุนัขStackTraceนั้นช้า - ดังนั้นควรใช้อย่างประหยัด
Jonathan Dickinson

214

อีกทางเลือกหนึ่งSystem.Diagnostics.StackTraceคือใช้System.Environment.StackTraceซึ่งส่งคืนการแทนค่าสตริงของ stacktrace

อีกตัวเลือกที่มีประโยชน์คือการใช้$CALLERและ$CALLSTACK ตัวแปรการดีบักใน Visual Studioเนื่องจากสามารถเปิดใช้งานได้โดยไม่ต้องสร้างแอปพลิเคชันขึ้นมาใหม่


6
Environment.StackTraceStackTraceเพียงใหม่ขึ้นตัวอย่างของ
Daniel

9
@Daniel: ใช่ แต่System.Environment.StackTraceอาจเป็นวิธีที่สะดวกกว่าในการเข้าถึงข้อมูลนั้น
larsmoa

6
@AndreiRinea: จริง ๆ แล้วฉันเชื่อว่าคุณสามารถเข้าถึงหมายเลขบรรทัดโดยใช้System.Diagnostics.StackTrace- ดูmsdn.microsoft.com/en-us/library/…
larsmoa

5
มันน่ารำคาญใช่มั้ยที่Environment.StackTraceเริ่มต้นด้วยเสมอat System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace()? นั่นไม่ใช่ส่วนหนึ่งของการติดตามสแต็กปัจจุบัน ณ จุดที่ใครบางคนกำลังมองหา
โรรี่

7
@Rory ดูที่ตัวสร้าง StackTrace (int skipFrames, bool fNeedFileInfo) คุณสามารถข้ามเฟรมเริ่มต้นได้ ipen วิธีการใน ILSpy และคุณสามารถดูว่ามันทำอะไร
วอลเตอร์ Vehoeven

39

มีสองวิธีในการทำเช่นนี้ System.Diagnostics.StackTrace()จะทำให้คุณมีร่องรอยสแต็กสำหรับหัวข้อปัจจุบัน หากคุณมีการอ้างอิงถึงThreadตัวอย่างเช่นคุณสามารถได้รับการติดตามสแต็คที่ผ่าน StackTrace()overloaded

คุณอาจต้องการดูคำถาม Stack Overflow วิธีรับ stacktrace ของเธรดที่ไม่เป็นปัจจุบัน .


16

คุณสามารถทำได้ในดีบักเกอร์ Visual Studio โดยไม่ต้องแก้ไขรหัส

  1. สร้างเบรกพอยต์ที่คุณต้องการดูการติดตามสแต็ก
  2. คลิกขวาที่เบรกพอยต์และเลือก "การกระทำ ... " ใน VS2015 ใน VS2010 เลือก "When Hit ... " จากนั้นเปิดใช้งาน "Print a message"
  3. ตรวจสอบให้แน่ใจว่าได้เลือก "ดำเนินการต่อ"
  4. พิมพ์ข้อความที่คุณต้องการพิมพ์
  5. เพิ่ม $ CALLSTACK ทุกที่ที่คุณต้องการดูการติดตามสแต็ก
  6. เรียกใช้โปรแกรมในดีบักเกอร์

แน่นอนว่าสิ่งนี้ไม่ได้ช่วยอะไรถ้าคุณใช้งานรหัสบนเครื่องอื่น แต่มันค่อนข้างมีประโยชน์มากที่จะสามารถสแต็กการติดตามสแต็กโดยอัตโนมัติโดยไม่ส่งผลกระทบต่อรหัสการเผยแพร่หรือไม่จำเป็นต้องรีสตาร์ทโปรแกรม


7
หากคุณต้องการดูร่องรอยการติดตามและคุณอยู่ใน VS debugger ที่เบรกพอยต์ให้ไปที่ Debug-> Windows-> Call Stack
khargoosh

5
ใช่ แต่ถ้าคุณทำเช่นนี้โปรแกรมไม่จำเป็นต้องหยุดให้คุณเห็น stack trace
Hank Schultz

7
Console.WriteLine(
    new System.Diagnostics.StackTrace().ToString()
    );

ผลลัพธ์จะคล้ายกับ:

ที่ YourNamespace.Program.executeMethod (String msg)

ที่ YourNamespace.Program.Main (String [] args)

แทนที่Console.WriteLineด้วยLogวิธีการของคุณ ที่จริงแล้วไม่มีความจำเป็นสำหรับ.ToString()กรณี Console.WriteLine objectในขณะที่มันยอมรับ แต่คุณอาจต้องใช้วิธี Log (string msg)


-2
   private void ExceptionTest()
    {
        try
        {
            int j = 0;
            int i = 5;
            i = 1 / j;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
            var stList = ex.StackTrace.ToString().Split('\\');
            Console.WriteLine("Exception occurred at " + stList[stList.Count() - 1]);
        }
    }

ดูเหมือนว่าจะทำงานให้ฉัน


3
นี่เป็นเพียงการสร้างข้อยกเว้นที่ชัดเจน ทำไม? ทำไมไม่ยกตัวอย่างข้อยกเว้นอย่างชัดเจนแทนที่จะเป็นข้อบกพร่องที่จะทำให้เกิดข้อยกเว้นในตัวของมันเอง? อะไรคือประโยชน์ของตรรกะการตรวจจับเพิ่มเติมที่จำเป็นสำหรับการยกเว้นจริง และถึงตอนนั้นคุณยังคงไม่สนใจคำถามที่โพสต์จริงเกี่ยวกับวิธีรับการติดตามสแต็กโดยไม่มีข้อยกเว้นใด ๆ (อ่านชื่อเรื่อง)
Flater

มันเป็นคำตอบที่ถูกต้อง แต่เป็นทางออกที่น่ากลัว ไม่มีใครควรใช้มัน ... @ ไม่ว่าคุณจะทำอะไรแทนที่ด้วยรหัสโคตรเหมือนคำตอบอื่น ๆ ที่แนะนำ
Tomer W
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.