2013-04-24 17 views
7

ExtendScriptでエラーを検出すると、そのスタックトレースを記録できるようにしたいと思います。エラーにはExtendScriptにスタックトレースが含まれていないように見えるので、私はスタックトレースをエラーに追加するという考え方をしています。ExtendScriptでエラーのスタックトレースを取得する

私がスタックトレースを取得するために知っている唯一の方法は$.stackです。フィールド$.stackには、そのフィールドにアクセスした時点の現在のスタックトレースが含まれています。

私の最初の試みは、スタックを含む私自身のエラーオブジェクトを作成することでした。 Errorオブジェクトは、それを作成したコードの行とファイル名を取得できる点で非常に特殊です。例えば、

try { 
    throw new Error("Houston, we have a problem."); 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
} 

が印刷されます:

Line: 2 
File: ~/Desktop/Source1.jsx 
Message: Houston, we have a problem. 

を私はそれがこの能力を使用して独自のオブジェクトを作成することはできないと思います。私が得ることができる最も近いがこれです:

印刷し
function MyError(msg, file, line) { 
    this.message = msg; 
    this.fileName = file; 
    this.line = line; 
    this.stack = $.stack; 
} 

try { 
    throw new MyError("Houston, we have a problem.", $.fileName, $.line); 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
    $.writeln("Stack: " + e.stack); 
} 

Line: 9 
File: ~/Desktop/Source2.jsx 
Message: Houston, we have a problem. 
Stack: [Source3.jsx] 
MyError("Houston, we have a p"...,"~/Desktop/Source2.js"...,9) 

をここでは、私は自分のエラーオブジェクトを作成し、明示的にMyErrorので、(それをラインとファイル名を渡していることがわかりますそれだけでそれを理解することはできません)。また、エラーが生成されたときに現在のスタックも含めました。

私自身のエラーオブジェクトを呼び出すとうまく動作しますが、他のコードが通常のエラーオブジェクトを呼び出すとき、またはエラーが自動的に生成されたとき(たとえば不正なアクセスによって)は機能しません。どのようにエラーが発生してもスタックトレースを取得できるようにしたい。

Errorのコンストラクタを変更したり、Errorのプロトタイプを変更したり、Errorオブジェクトを完全に置き換えたりする方法もあります。私はこれらのアプローチのいずれかを働かせることができませんでした。

もう一つのアイデアは、自分のコードのすべての単一のメソッドにcatchブロックを置き、それがまだない場合は現在のスタックをエラーに追加することです。可能であればこのオプションを避けたいと思います。

私はアイデアがありません。エラーのスタックトレースを取得する方法はありますか?

+0

私は本当に興味を持っています。私の最大の問題は、私がエラーから何も役に立たないjsxbin形式にコンパイルするとすぐです。私はそれからデバッグできるように、起こっているロギングの膨大な量のルートを行ってきました。 –

+0

Personnaly私は$ .writeまたは$ .writeln命令を使用していません。まず最初に開いていなければExtendScript Toolkitを先に持ってくるでしょう。彼らが警告していなければ、それは本当にエンドユーザを混乱させるかもしれません。また、特に実際には内部ループが遅くなることがあります。 ログファイルをディスクに書き込む方が好きです。私は自分のレシピを持っていますが、このライブラリを利用することができます:http://creative-scripts.com/logging-with-a-smile/ – Loic

答えて

1

これは完璧ではありませんが、部分的な解決策が見つかりました。

ファクト1:Error.prototypeはエラーオブジェクトです。

ファクト2:エラーが発生するといつでもError.prototype.toStringメソッドが呼び出されます。

ファクト3:フィールドError.prototype.toStringは変更することができます。

通常、このメソッドは文字列 "Error"を返します。そのため、スタックを格納し、文字列 "Error"を返す独自のメソッドに置き換えることができます。

Error.prototype.toString = function() { 
    if (typeof this.stack === "undefined" || this.stack === null) { 
     this.stack = "placeholder"; 
     // The previous line is needed because the next line may indirectly call this method. 
     this.stack = $.stack; 
    } 
    return "Error"; 
} 

try { 
    throw new Error("Houston, we have a problem."); 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
    $.writeln("Stack: " + e.stack); 
} 

結果:

Line: 11 
File: ~/Desktop/Source10.jsx 
Message: Houston, we have a problem. 
Stack: [Source10.jsx] 
toString() 

それは働きます!唯一の問題は自動エラーです。

Error.prototype.toString = function() { 
    if (typeof this.stack === "undefined" || this.stack === null) { 
     this.stack = "placeholder"; 
     // The previous line is needed because the next line may indirectly call this method. 
     this.stack = $.stack; 
    } 
    return "Error"; 
} 

try { 
    var foo = null; 
    foo.bar; 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
    $.writeln("Stack: " + e.stack); 
} 

結果:

Line: 12 
File: ~/Desktop/Source12.jsx 
Message: null is not an object 
Stack: undefined 

だから、それはすべてのエラーが、その進捗状況では動作しません。

2

私は別の解決策を考え出しましたが、これはコードの一部を変更する必要があります。

myObject.myMethod1("Hello", "world"); 

あなたはこのようなメソッドを呼び出すに切り替える必要があります:

myObject.do("myMethod1", "Hello", "world"); 

ここにそれがどのように動作するかの完全な例です:

Object.prototype.do = function stackHelper() { 
    // Convert the arguments into an array. 
    var argumentArray = Array.prototype.slice.call(arguments); 
    // Remove the first argument, which is the function's name. 
    var functionString = argumentArray.shift(); 
    try { 
     this[functionString].apply(this, argumentArray); 
    } 
    catch (e) { 
     if (typeof e.stack === "undefined" || e.stack === null) { 
      e.stack = $.stack; 
     } 
     throw e; 
    } 
}; 

var myObject = { 
    myMethod1: function myMethod1(myArg1, myArg2){ 
     this.do("myMethod2", myArg1, myArg2); 
    }, 

    myMethod2: function myMethod2(myArg1, myArg2){ 
     this.do("myMethod3", myArg1, myArg2); 
    }, 

    myMethod3: function myMethod3(myArg1, myArg2){ 
     $.writeln(myArg1 + ", " + myArg2 + "!"); 
     var foo = null; 
     foo.bar; // Throws an error. 
    }, 
}; 

try { 
    myObject.do("myMethod1", "Hello", "world"); 
} 
catch (e) { 
    $.writeln("Stack: " + e.stack); 
} 

代わりに、いつものようにメソッドを呼び出します出力は次のようになります。

Hello, world! 
Stack: [do.jsx] 
stackHelper("myMethod1","Hello","world") 
myMethod1("Hello","world") 
stackHelper("myMethod2","Hello","world") 
myMethod2("Hello","world") 
stackHelper("myMethod3","Hello","world") 

それは素晴らしい解決策ではありませんが、少なくともそれはすべてのエラーで機能します。

0

カスタムメッセージを表示するだけでよい場合は、このコードを記述しました。 私はそれが解決したと思います...私にとっては大丈夫です。

try 
{ 
    app.selection[0].contents = 1 
} 
catch (myError) 
{ 
    alert(myError.number); // For check the number error 
    if (myError.number == 30477) 
    { 
     alert("Mensagem Edu\n" + "Line: " + myError.line + "\n" + "File: " + myError.fileName + "\n" + "Message: " + myError.message + "\n" + "Stack: " + myError.stack); 
     exit(); 
    } 
    else (myError); 
    {} 
    exit(); 
} 
+0

誰かが 'myError.stack'に対して' undefined'以外を取得していますか? OPの質問のポイントですか? –

1

Error.prototype.toString機能の[ネイティブコード]を変更することはできません。だから私はこの解決策を考え出した:

function ReturnCustomErrorString(e, additionalMessage) 
{ 
    try { 
     var errorString = e.toString(); 
     errorString = errorString.concat("\n", "additionalMessage: " + additionalMessage + "\n", "file: " + e.fileName + "\n", "line: " + e.line + "\n", "stack-trace: \n" + $.stack); 
     return errorString; 
    } 
    catch (e) { 
     alert("Error in : " + ReturnCustomErrorString.name + "(...)\n" + e); 
     exit(); 
    } 
} 

使用法:

try { 
    // code that does throw an error 
} catch (e) { 
    alert(ReturnCustomErrorString(e)); 
} 

私は私が頻繁にキャッチブロックで、このようなものでした。この機能を書いた前に:今

alert(e); 

をI私はalert(ReturnCustomErrorString(e));をやっていますが、はるかに有用な情報が得られます。ですから、現時点では、このソリューションはかなり良いと思います。

関連する問題