The only difference I have found so far: If a script that is run by app.doScript returns an error, the file and line number of the error are overridden by the file and line number of the app.doScript call.
Are there any other differences I should know about?
Here's sample code that demonstrates the above difference:
First run InDesign:
c:
cd "C:\Program Files\Adobe\Adobe InDesign CS6 Server x64"
InDesignServer.com -port 12345
pause
Next create a batch file to run a script:
c:
cd "C:\Program Files\Adobe\Adobe InDesign CS6 Server x64"
sampleclient -host localhost:12345 -server "C:/doscript_vs_evalfile/call_doScript.jsx"
pause
This is "call_doScript.jsx", which will call app.doScript.
try {
app.doScript(new File("/c/doscript_vs_evalfile/called_by_doScript.jsx"));
"Success";
}
catch (e) {
var sError = "Encountered " + e.name + " #" + e.number + " at line " + e.line + " of file " + e.fileName + "\n" + e.message;
app.consoleout(sError);
sError;
}
This is "called_by_doScript.jsx", which is called by the previous script:
app.consoleout("Running called_by_doScript.jsx");
// Produce error
var a = b;
Run the batch file and this is the result:
02/25/13 13:30:03 INFO [javascript] Executing File: C:\doscript_vs_evalfile\call_doScript.jsx
02/25/13 13:30:03 INFO [javascript] Executing File: C:\doscript_vs_evalfile\called_by_doScript.jsx
02/25/13 13:30:03 INFO [script] Running called_by_doScript.jsx
02/25/13 13:30:03 INFO [script] Encountered ReferenceError #2 at line 2 of file /c/doscript_vs_evalfile/call_doScript.jsx
b is undefined
Notice that the error above is incorrect. The error was caused by line 3 of called_by_doScript, not line 2 of call_doScript.
Now modify the scripts to use $.evalFile, and we get this result:
02/25/13 13:32:39 INFO [javascript] Executing File: C:\doscript_vs_evalfile\call_evalFile.jsx
02/25/13 13:32:39 INFO [script] Running called_by_evalFile.jsx
02/25/13 13:32:39 INFO [script] Encountered ReferenceError #2 at line 3 of file /c/doscript_vs_evalfile/called_by_evalFile.jsx
b is undefined
Notice that the error is now reported at the correct location.
Edit:
I found sparse documentation. It doesn't really answer my question, but it does describe different optional parameters.
doScript: Adobe InDesign CS6 Scripting Guide: JavaScript (direct link)
See page 16, "Using the doScript Method"
evalFile: Javascript Tools Guide: Adobe Creative Suite 5
See page 219
$.evalFile is an ExtendScript feature while app.doScript is implemented by InDesign.
$.evalFile does
maintain the $.stack
consider $.includePath
work in other target applications
app.doScript can
pass arguments
change the language, e.g. AppleScript
use #targetengine to address other sessions
modify the undo/transaction mode as far as supported
but ...
nested doScript calls overwrite arguments
in a complicated setup I had trouble to debug after passing more than 12 arguments.
single stepping across doScript is trouble
Also, as you found, error handling differs. Keep an eye on exceptions ...
Related
so I am using zsh. I have a bunch of functions that move me around the place - like if I type "bin" anywhere - I go to ~/bin etc. I do this by hooking into the command_not_found_handler as so:
command_not_found_handler() {
if [ -f ~/bin/marked/$1 ]; then
directory=$(<~/bin/marked/$1)"
echo cd \"$directory\" >~/source_function
return 0
...
and this works fantastically - anywhere I am, I can just type marker blah - it creates a marker, and from then on anywhere I am, if I type blah it will just go back to that directory I marked.
Except.
I have "." in my path. (Yes I know you think I shouldn't do that)
and if there happens to be a "blah" file in the current directory - instead of going to the command not found handler - it tries to execute that, and its of course not an executable script, so I get "Permission Denied"
Is there any way to trap this permission denied, like I trap the command not found? It really hits me a lot with the word "scripts" - because I like typing scripts to take me to my personal scripts directory - but every program I write also has a scripts directory in the git repo for scripts related to that repository.
Aside from removing . from your path (which you don't want to do), I don't see a way to configure zsh to avoid executing (or attempting to execute) files that match the given command in the current directory. zsh has lots of options, but I don't see documentation describing any relevant ones, nor do I see source code support for one.
I make this claim based on reading the source code for zsh's handling in the execute() function at https://sourceforge.net/p/zsh/code/ci/master/tree/Src/exec.c. Here, when zsh sees dot (.) in the path, it attempts to execute a file by that name in that directory:
for (pp = path; *pp; pp++)
if (!(*pp)[0] || ((*pp)[0] == '.' && !(*pp)[1])) {
ee = zexecve(arg0, argv, newenvp);
if (isgooderr(ee, *pp))
eno = ee;
} else {
z = buf;
strucpy(&z, *pp);
*z++ = '/';
strcpy(z, arg0);
ee = zexecve(buf, argv, newenvp);
if (isgooderr(ee, *pp))
eno = ee;
}
After that, the execute() function reaches the code below and calls zerr(), which produces the "permission denied" error message:
if (eno)
zerr("%e: %s", eno, arg0);
else if (commandnotfound(arg0, args) == 0)
_realexit();
else
zerr("command not found: %s", arg0);
... and there is no logic in the code to intercept zsh's behavior in that case.
My best suggestion to achieve the desired result is to remove dot (.) from your path.
I'm trying to implement the touch command from the unix command line, but it seems that my last line throws an exception: ** Exception: ~/.todo: openFile: does not exist (No such file or directory)
main = touch "~/.todo"
touch :: FilePath -> IO ()
touch name = do
exists <- doesFileExist name
unless exists $ appendFile name ""
If there is any OS specific behavior, I'm testing from macOS Sierra.
I feel as if this error is strange in that the documentation for openFile states that
If the file does not exist and it is opened for output, it should be created as a new file.
Any suggestions as to how to fix this?
Edit: According to #chi, the touch command should always open the file, even if it already exists, because it will then update the file's last modified date.
touch :: FilePath -> IO ()
touch name = appendFile name ""
Use touchFile from the unix package (System.Posix.Files.ByteString).
appendFile name "" does not work like touch; appendFile is a no-op when the string to append is empty.
You can confirm this by running stat on the file before and after and comparing the modification times.
In the future please paste all the code you are using that creates the error. This includes both the imports and the invocation. In your case it seems you are running something with a shell expansion character:
*Main> touch "~/foobar"
*** Exception: ~/foobar: openFile: does not exist (No such file or directory)
The ~ is typically expanded by a shell (there also exists a C library that can do that rewriting for you). Most languages actually interpret that as a literal part of the path... but the ~ directory probably doesn't exist or that symbol might not even be valid depending on your platform.
Instead try a valid file path:
*Main> touch "/tmp/thisfile"
*Main>
Leaving GHCi.
% ls -l /tmp/thisfile
-rw-rw-r--. 1 theuser theuser 0 Feb 3 12:51 /tmp/thisfile
I want to execute a batch file using People code in Application Engine Program. But The program have an issue returning Exec code as a non zero value (Value - 1).
Below is people code snippet below.
Global File &FileLog;
Global string &LogFileName, &Servername, &commandline;
Local string &Footer;
If &Servername = "PSNT" Then
&ScriptName = "D: && D:\psoft\PT854\appserv\prcs\RNBatchFile.bat";
End-If;
&commandline = &ScriptName;
/* Need to commit work or Exec will fail */
CommitWork();
&ExitCode = Exec("cmd.exe /c " | &commandline, %Exec_Synchronous + %FilePath_Absolute);
If &ExitCode <> 0 Then
MessageBox(0, "", 0, 0, ("Batch File Call Failed! Exit code returned by script was " | &ExitCode));
End-If;
Any help how to resolve this issue.
Best bet is to do a trace of the execution.
Thoughts:
Can you log on the the process scheduler you are running this on and execute the script OK?
Is the AE being scheduled or called at run-time?
You should not need to change directory as you are using a fully qualified path to the script.
you should not need to call "cmd /c" as this will create an additional shell for you application to run within, making debuging harder, etc.
Run a trace, and drop us the output. :) HTH
What about changing the working directory to D: inside of the script instead? You are invoking two commands and I'm wondering what the shell is returning to exec. I'm assuming you wrote your script to give the appropriate return code and that isn't the problem.
I couldn't tell from the question text, but are you looking for a negative result, such as -1? I think return codes are usually positive. 0 for success, some other positive number for failure. Negative numbers may be acceptable, but am wondering if Exec doesn't like negative numbers?
Perhaps the PeopleCode ChDir function still works as an alternative to two commands in one line? I haven't tried it for a LONG time.
Another alternative that gives you significant control over the process is to use java.lang.Runtime.exec from PeopleCode: http://jjmpsj.blogspot.com/2010/02/exec-processes-while-controlling-stdin.html.
I'd like to modify CPD to only spit out the Found a X line (Y tokens) duplication in the following files: ... when generating a report, i.e. suppress the source lines of code. I have the /src/ files and attempted to modify SimpleRenderer.java in /src/net/sourceforge/pmd/cpd/ by commenting out
String source = match.getSourceCodeSlice();
if (trimLeadingWhitespace) {
String[] lines = source.split("[" + PMD.EOL + "]");
int trimDepth = StringUtil.maxCommonLeadingWhitespaceForAll(lines);
if (trimDepth > 0) {
lines = StringUtil.trimStartOn(lines, trimDepth);
}
for (int i=0; i<lines.length; i++) {
rpt.append(lines[i]).append(PMD.EOL);
}
return;
}
However the report has not changed. I'm a bit of a Java novice, so keep that in mind. Do I need to rebuild the pmd-4.2.x in Eclipse somehow?
There are different ways to achieve this:
Without modifying PMD/CPD at all by using egrep. You can e.g. post-filter the report:
bin/run.sh cpd --minimum-tokens 100 --files src --encoding UTF-8 \
| egrep "^Found a |^Starting at line "
This would output now only the lines which start with "Found a " or "Starting at line ".
Modifying PMD/CPD to adjust the report format. I would however suggest, to implement this modified report format as a separate format, e.g. naming it "text_without_sources", rather than changing the default format. You would then call CPD with bin/run.sh cpd --format text_without_sources ....
In that case, you'll need to build PMD from sources. PMD uses Maven to build (you can use eclipse during development - but the package is built with maven). After a mvn clean package in the top-directory of the cloned sources from https://github.com/pmd/pmd you'll find the binary in the directory pmd-dist/target/.
Look at how the reports are integrated in CPDConfiguration.java - you can add your own version of the SimpleRenderer.
Create a feature-request at https://sourceforge.net/p/pmd/bugs/
I have created a simple test application
with the following code
var i : int;
for (i=0; i<3000000; i++){
trace(i);
}
When I run the application, it's very slow to load, which means the "trace" is running.
I check the flash player by right-clicking, the debugger option is not enable.
So I wonder if there is an option to put in compiler to exclude the trace.
Otherwise, I have to remove manually all the trace in the program.
Are there any other options of compiler to optimize the flex application in a maximum way?
There is a really sweet feature built into Flex called the logging API (you can read more about it here http://livedocs.adobe.com/flex/3/html/logging_09.html).
Basically, you log (trace) things in a different way, admittedly with slightly more code than a standard trace, but it allows you much greater flexibility. This is an example:
import mx.logging.Log;
Log.getLogger("com.edibleCode.logDemo").info("This is some info");
Log.getLogger("com.edibleCode.logDemo").error("This is an error");
Then all you need to do is create a trace target in your main application file, something like:
<mx:TraceTarget id="logTarget" fieldSeparator=" - " includeCategory="true" includeLevel="true" includeTime="true">
<mx:filters>
<mx:Array>
<mx:String>*</mx:String>
</mx:Array>
</mx:filters>
<!--
0 = ALL, 2 = DEBUG, 4 = INFO, 6 = WARN, 8 = ERROR, 1000 = FATAL
-->
<mx:level>0</mx:level>
</mx:TraceTarget>
And register the trace with:
Log.addTarget(logTarget);
This provides several benefits over the normal trace:
You can filter (turn off) traces to only see what you want:
Either by modifying the filters array
Or the level to show only error or fatal messages
You can replace the trace target with any other type of logging interface, e.g.
A TextField
A text file
Use conditional compilation, more here.
In your code set:
CONFIG::debugging {
trace(i);
}
Then go to Project->Properties->Flex Compiler and add
-define=CONFIG::debugging,false
or
-define=CONFIG::debugging,true
You could do a find/replace on the entire project. search for 'trace(' and replace with '//trace('. That would be quick enough and easily undone.
The mxmlc argument debug allows you to add or remove debug features from SWF files. The value of the debug argument is false by default for the command line compiler, but in Flex Builder, you have to manually create a non-debug SWF. According to the documentation on compiler arguments, debug information added to the SWF includes "line numbers and filenames of all the source files". There is no mention of trace() function calls, and I don't think there's a way to remove them through a compiler argument, but you're welcome to check the linked document for the entire list of available arguments.
There are two compiler options that you should set: -debug=false -optimize=true. In Flex Builder or Eclipse, look under Project->Properties->Flex Compiler and fill in the box labeled "Additional compiler arguments."
Go to your flex code base directory (and shut down Flex Builder if its running - it gets uppity if you change things while it's running). Run this to change all your trace statements. I recommend checking the tree into git or something first and then running a diff afterwards (or cp -r the tree to do a diff -r or something). The only major case this will mess up is if you have semicolons inside trace strings:
find . -name '*.as' -exec perl -pe 'BEGIN{ undef $/; }s/trace([^;]*);/CONFIG::debugging { trace $1 ; };/smg;' -i {} \;
find . -name '*.mxml' -exec perl -pe 'BEGIN{ undef $/; }s/trace([^;]*);/CONFIG::debugging { trace $1 ; };/smg;' -i {} \;
Then set up the following in your Project->Properties->Flex Compiler->Additional compiler arguments:
-define=CONFIG::debugging,true -define=CONFIG::release,false
And use:
CONFIG::release { /* code */ }
for the "#else" clause. This was the solution I picked after reading this question and answer set.
Also beware this:
if( foo )
{
/*code*/
}
else
CONFIG::debugging { trace("whoops no braces around else-clause"); };
I.e. if you have ONLY one of these in an if or else or whatever block, and its a naked block with no braces, then regardless of whether it's compiled out, it will complain.
Something else you could do is define a boolean named debugMode or something in an external constants .as file somewhere and include this file in any project you use. Then, before any trace statement, you could check the status of this boolean first. This is similar to zdmytriv's answer.
Have to say, I like edibleCode's answer and look forward to trying it some time.