Adobe 获取ExtendScript中错误的堆栈跟踪

Adobe 获取ExtendScript中错误的堆栈跟踪,adobe,adobe-indesign,extendscript,indesign-server,Adobe,Adobe Indesign,Extendscript,Indesign Server,当我在ExtendScript中发现错误时,我希望能够记录其堆栈跟踪。在ExtendScript中,错误似乎不包含堆栈跟踪,因此我正在考虑将堆栈跟踪添加到错误中 据我所知,获取堆栈跟踪的唯一方法是$.stack。字段$。stack包含访问该字段时的当前堆栈跟踪 我的第一次尝试是创建自己的包含堆栈的错误对象。Error对象非常特殊,因为它可以获取创建它的代码的行和文件名。比如说, 试试看{ 抛出新错误(“休斯顿,我们有问题。”); } 捕获(e){ $.writeln(“行:+e.Line”);

当我在ExtendScript中发现错误时,我希望能够记录其堆栈跟踪。在ExtendScript中,错误似乎不包含堆栈跟踪,因此我正在考虑将堆栈跟踪添加到错误中

据我所知,获取堆栈跟踪的唯一方法是
$.stack
。字段
$。stack
包含访问该字段时的当前堆栈跟踪

我的第一次尝试是创建自己的包含堆栈的错误对象。
Error
对象非常特殊,因为它可以获取创建它的代码的行和文件名。比如说,

试试看{
抛出新错误(“休斯顿,我们有问题。”);
}
捕获(e){
$.writeln(“行:+e.Line”);
$.writeln(“文件:+e.fileName”);
$.writeln(“Message:+e.Message”);
}
将打印:

Line: 2
File: ~/Desktop/Source1.jsx
Message: Houston, we have a problem.
我认为不可能用这种能力创建自己的对象。我能得到的最接近的结果是:

函数MyError(消息、文件、行){
this.message=msg;
this.fileName=文件;
this.line=line;
this.stack=$.stack;
}
试一试{
抛出新的MyError(“休斯顿,我们有问题。”,$.fileName,$.line);
}
捕获(e){
$.writeln(“行:+e.Line”);
$.writeln(“文件:+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块,如果当前堆栈还没有,则将其添加到错误中。如果可能的话,我想避免这个选择


我没有主意了。有什么方法可以得到错误的堆栈跟踪吗?

这并不完美,但我找到了部分解决方案

事实1:
错误。原型是一个错误对象

事实2:每当创建错误时,就会调用方法
Error.prototype.toString

事实3:可以修改字段
Error.prototype.toString

该方法通常只返回字符串“Error”,因此我们可以将其替换为存储堆栈的方法,然后返回字符串“Error”

Error.prototype.toString=function(){
if(typeof this.stack==“undefined”| | this.stack===null){
this.stack=“占位符”;
//需要上一行,因为下一行可能间接调用此方法。
this.stack=$.stack;
}
返回“错误”;
}
试一试{
抛出新错误(“休斯顿,我们有问题。”);
}
捕获(e){
$.writeln(“行:+e.Line”);
$.writeln(“文件:+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()
Line: 12
File: ~/Desktop/Source12.jsx
Message: null is not an object
Stack: undefined
它起作用了!唯一的问题是自动错误

Error.prototype.toString=function(){
if(typeof this.stack==“undefined”| | this.stack===null){
this.stack=“占位符”;
//需要上一行,因为下一行可能间接调用此方法。
this.stack=$.stack;
}
返回“错误”;
}
试一试{
var foo=null;
foo.bar;
}
捕获(e){
$.writeln(“行:+e.Line”);
$.writeln(“文件:+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()
Line: 12
File: ~/Desktop/Source12.jsx
Message: null is not an object
Stack: undefined

因此,它不能处理所有的错误,但可以处理它的进度。

我提出了另一个解决方案,尽管这个解决方案要求您更改一些代码。不要像往常一样调用方法:

myObject.myMethod1(“你好”,“世界”);
您需要切换到如下调用方法:

Hello, world!
Stack: [do.jsx]
stackHelper("myMethod1","Hello","world")
myMethod1("Hello","world")
stackHelper("myMethod2","Hello","world")
myMethod2("Hello","world")
stackHelper("myMethod3","Hello","world")
myObject.do(“myMethod1”、“你好”、“世界”);
下面是它工作原理的完整示例:

Object.prototype.do=函数stackHelper(){
//将参数转换为数组。
var argumentArray=Array.prototype.slice.call(参数);
//删除第一个参数,即函数名。
var functionString=argumentArray.shift();
试一试{
此[functionString].apply(此,argumentArray);
}
捕获(e){
if(e.stack的类型==“未定义”| | e.stack===null){
e、 stack=$.stack;
}
投掷e;
}
};
变量myObject={
myMethod1:函数myMethod1(myArg1,myArg2){
this.do(“myMethod2”,myArg1,myArg2);
},
myMethod2:函数myMethod2(myArg1,myArg2){
this.do(“myMethod3”,myArg1,myArg2);
},
myMethod3:函数myMethod3(myArg1、myArg2){
$.writeln(myArg1+“,+myArg2+”!”;
var foo=null;
foo.bar;//抛出一个错误。
},
};
试一试{
myObject.do(“myMethod1”、“你好”、“世界”);
}
捕获(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")

这不是一个很好的解决方案,但至少它可以处理所有错误。

如果您只需要显示自定义消息,我编写了以下代码。 我想这已经解决了。。。对我来说没关系

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();
}

据我所知,您无法修改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)); 
}
在编写此函数之前,我经常在catch块中执行以下操作:

alert(e);
现在我正在做
alert(ReturnCustomErrorString(e)),但我得到的比你多得多