2017-04-01 61 views
0

我一直在試圖獲得在移動設備上運行時打印堆棧跟蹤的可靠方法。我碰到System.Environment.StackTrace跳過堆棧跟蹤中顯示的特定方法

來到我想的東西有3類現在:

public class Test : MonoBehaviour { 
    public static void Do() { 
     Test3.ActionThing(() => { 
      Test2.DoSomethingElse(); 
     }); 
    } 
} 


public class Test2 : MonoBehaviour { 
    void Start() { 
     Test3.ActionThing(() => { 
      Debug.Log("Start execution"); 
      Test.Do(); 
     }); 
    } 

    public static void DoSomethingElse(){ 
     Test3.ActionThing(() => { 
      var a = 0; 
      a = int.Parse("s1"); 
     }); 
    } 
} 

public class Test3 : MonoBehaviour { 
    public static void ActionThing(Action act){ 
     try{ 
      if (act != null) 
       act(); 
     }catch(Exception e){ 
      Debug.LogError("Error occured " + e.Message); 
      Debug.LogError("StackTrace was " + Environment.StackTrace); 
     } 
    } 
} 

我得到當錯誤被拋出

StackTrace was at System.Environment.get_StackTrace() in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Environment.cs:line 227 
    at Test3.ActionThing(System.Action act) in <ProjectPath>\Test3.cs:line 13 
    at Test2.DoSomethingElse() in <ProjectPath>\Test2.cs:line 14 
    at Test.<Do>m__0() in <ProjectPath>\Test.cs:line 8 
    at Test3.ActionThing(System.Action act) in <ProjectPath>\Test3.cs:line 10 
    at Test.Do() in <ProjectPath>\Test.cs:line 7 
    at Test2.<Start>m__0() in <ProjectPath>\Test2.cs:line 9 
    at Test3.ActionThing(System.Action act) in <ProjectPath>\Test3.cs:line 10 
    at Test2.Start() in <ProjectPath>\Test2.cs:line 7 
UnityEngine.Debug:LogError(Object) 
Test3:ActionThing(Action) (at Assets/Test3.cs:13) 
Test2:DoSomethingElse() (at Assets/Test2.cs:14) 
Test:<Do>m__0() (at Assets/Test.cs:8) 
Test3:ActionThing(Action) (at Assets/Test3.cs:10) 
Test:Do() (at Assets/Test.cs:7) 
Test2:<Start>m__0() (at Assets/Test2.cs:9) 
Test3:ActionThing(Action) (at Assets/Test3.cs:10) 
Test2:Start() (at Assets/Test2.cs:7) 

顯然,這堆棧跟蹤,因爲我想這是一個在發佈版本中調試,它不會顯示內部堆棧跟蹤,只顯示消息。

但問題出在堆棧跟蹤本身,它甚至打印方法at Test3.ActionThing(System.Action act) in <ProjectPath>\Test3.cs:line 10。我想跳過堆棧跟蹤中顯示的內容。

 

任何幫助表示讚賞,謝謝提前。如果問題似乎太長,請建議編輯:)

+0

?處理'Environment.StackTrace'並刪除不需要的行將是一件簡單的事情,但它不清楚是什麼讓一些行可以接受,而其他的不行 –

+0

該方法的一般想法是通過它路由所有代碼,以便如果它拋出錯誤,我可以在1個地方看到/打印它們。但是如果被調用的方法鏈太長,並且所有東西都通過所述方法進行路由,那麼這個字符串會很長,並且會使得錯誤不易於快速理解,以及不必要的堆棧條目 – Shraa1

+0

我認爲你不會'不想'System.Environment.get_StackTrace()'? –

回答

0

最簡單的方法是簡單地處理Environment.StackTrace字符串,並剔除不關心的堆棧幀。

public static void ActionThing(Action act){ 
    try{ 
     if (act != null) 
      act(); 
    }catch(Exception e){ 
     var relevantStackFrames = 
      Environment.StackTrace 
       .Split('\n') 
       .Skip(2) 
       .ToArray(); 
     var relevantStackTrace = string.Join("\n", relevantStackFrames); 
     Debug.LogError("Error occured " + e.Message); 
     Debug.LogError("StackTrace was " + relevantStackTrace); 
    } 
} 

線我們分配給relevantStackFrames拆分堆棧跟蹤字符串轉換成一個字符串數組,其中每個元素爲一個相應的堆棧幀的行。 System.Environment.get_StackTrace()Test3.ActionThing(System.Action act)的堆棧幀是此數組中的前兩個元素,因爲您不需要它們,所以我們使用linq的Skip函數將它們從集合中排除。然後我們將跳轉操作的結果轉換成一個數組ToArray。所以relevantStackFrames是一個堆棧幀串的數組,除了你不想要的。

然後我們創建一個名爲relevantStackTrace的字符串,它將包含整個堆棧跟蹤的字符串。我們只加入relevantStackTrace的每個元素,並將換行符用string.Join

記住添加using System.Linq那麼,爲什麼你不想要的`Test3.ActionThing(System.Action行爲)`在堆棧跟蹤線路可以訪問SkipToArray

+0

我已經使用toarray和string.Join之前。我還沒有使用過Skip,所以我不確定它是如何工作的。但通過方法名稱猜測,它會跳過堆棧跟蹤的拆分數組中的第二個元素。如果方法鏈不同,這是一個硬編碼值,可能無法一直工作。 – Shraa1

+0

我自己曾經考慮過字符串操作,但我並不是那種通常的粉絲。我會接受這個答案,如果這有效,並沒有更好的解決方案。再次感謝 – Shraa1

+0

我認爲硬編碼值在這種情況下不是問題,因爲您始終知道您要跳過多少幀(錯誤處理函數和調用堆棧獲取器)。但是如果你真的需要,你可以做更復雜的事情,比如過濾掉包含你不知道的函數的棧幀。 –