33

Typically when you're writing a .jsx script to automate an Adobe product (like InDesign, Illustrator or Photoshop), you write, debug and execute the script from the ExtendScript IDE. Is it possible to bypass ExtendScript and run the script from a third program?

I think Adobe products have a built-in JavaScript interpreter which ExtendScript can connect to to access the Adobe object models and automate their software. I'd like to be able to connect directly to that interpreter and run jsx files just as I would in ExtendScript.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Thomas
  • 5,736
  • 8
  • 44
  • 67

7 Answers7

37

Are you on a Mac? If so, you can use AppleScript with the osascript tool to execute your JavaScript. Here are some examples:

Running JSX and Returning a Value

Save this as ~/temp/foo.scpt:

tell application "Adobe Illustrator"
     -- 'do javascript' runs any arbitrary JS.
     -- We're using the #include feature to run another
     -- file. (That's an Adobe extension to JS.)
     --
     -- You have to pass a full, absolute path to #include.
     --
     -- The documentation alleges that 'do javascript'
     -- can be passed an AppleScript file object, but
     -- I wasn't able to get that to work.
     do javascript "#include ~/temp/foo.jsx"
end tell

And save this as ~/temp/foo.jsx:

var doc = app.activeDocument;
var numLayers = doc.layers.length;

// The last value in the JSX file will be printed out by
// osascript. 
numLayers;

Now, from the command line run osascript ~/temp/foo.scpt It will print the number of layers in the active Illustrator document.

Getting data out of the JavaScript is limiting. You can't print to stdout from within the JavaScript. Instead, place the value you want to return as the last statement of the JSX file; it will be printed by osascript. (Here's why: The last value in the JSX file is the return value of the do javascript AppleScript statement. That is also the last value in the AppleScript file, and osascript prints the final value.)

The value you return from JavaScript can be a number, a string, an array, or anything else that retains its value when converted to a string. If you want to return a complex object, you'll need to #include a JSON library and call .toJSONString() on the object.

Passing Arguments to JSX

To pass arguments to the JSX code, follow this example:

File ~/temp/args.scpt:

on run argv
    tell application "Adobe Illustrator"
        set js to "#include '~/temp/args.jsx';" & return
        set js to js & "main(arguments);" & return
        do javascript js with arguments argv
    end tell
end run

File ~/temp/args.jsx

function main(argv) {
    var layer = app.activeDocument.activeLayer;
    app.defaultStroked = true; 
    app.defaultFilled = true;

    // Top, left, width, height (in points).
    // Note that parameters start at argv[0].
    layer.pathItems.rectangle(argv[0], argv[1], argv[2], argv[3]);
}

And then run osascript args.scpt 50 30 10 80

Debugging

The do javascript command also has options for launching the ExtendScript debugger. For details, open the Illustrator dictionary in AppleScript Editor.

Evan
  • 2,400
  • 1
  • 18
  • 34
  • 3
    What about Windows? Any ideas? – David May 23 '13 at 23:52
  • This is how you run a file directory: on run argv tell application "Adobe Illustrator" set f to POSIX file "#{file}" as alias do javascript f with arguments argv end tell end run – justingordon Mar 16 '14 at 09:20
  • @David check out my answer for windows – jfizz Sep 04 '14 at 03:02
  • Do you know if the result value in AppleScript can be reused in any way? I'd like AppleScript to react differently depending on the value returned by JavaScript. Thanks. – ALx Jan 14 '15 at 17:04
  • Aleksander: Can you post a new question that goes into a bit more detail about what you'd like to do – Evan Jan 15 '15 at 05:29
  • Worked for me after I changed the first line to `tell application "Adobe Photoshop CC 2017"` – Max Heiber Dec 13 '16 at 19:24
  • I had to change `do javascript "..."` to `do script "..." language javascript`. – crishoj Mar 24 '19 at 21:34
  • This is how I do it in jasminejsx using JXA to JSX. https://github.com/theasci/jasminejsx/blob/ff5f6e5/run.sh#L11 – spyle Sep 20 '19 at 13:53
16

For Windows users, you can use a vbs script. Pass arguments to the .jsx script by providing arguments to the cscript command like so: cscript test.vbs "hello". test.vbs could look like so:

Dim appRef
Dim javaScriptFile
Dim argsArr()

Dim fsObj : Set fsObj = CreateObject("Scripting.FileSystemObject")
Dim jsxFile : Set jsxFile = fsObj.OpenTextFile("C:\Users\path\test.jsx", 1, False)
Dim fileContents : fileContents = jsxFile.ReadAll
jsxFile.Close
Set jsxFile = Nothing
Set fsObj = Nothing

javascriptFile = fileContents & "main(arguments);"

Set appRef = CreateObject("Illustrator.Application")

ReDim argsArr(Wscript.Arguments.length-1)

For i = 0 To Wscript.Arguments.length-1
    argsArr(i) = Wscript.Arguments(i)
Next

Wscript.Echo appRef.DoJavaScript(javascriptFile, argsArr, 1)

The Wscript.Echo will return the last line returned by the .jsx file. A .jsx file example could be:

function main(argv) {
    alert(argv[0]);
    return "test";
}

When ran, you should seee Illustrator (or whatever adobe program) alert "hello" and then "test" will be returned to stdout (you should see it in the command prompt window).

jfizz
  • 465
  • 5
  • 17
  • 1
    FYI, for those who like to stick with all javascript, the solution here, could be re-written as Microsoft JScript. It would then be a version of javascript (that can execute ActiveX/COM calls) to execute the actual JSX javascript code. – David Nov 19 '14 at 22:52
  • 2
    If you have multiple versions of an Adobe application installed use Illustrator.Application.xx where xx is the version number (decimal) to get the one you want. – C.O. May 04 '15 at 18:52
  • If you are running Windows x64 and would like the 32 bit version of Photoshop for example to come up make a Batch file with the following content to run your example script: START C:\Windows\SysWOW64\cmd.exe /K "cscript test.vbs hello" – C.O. May 04 '15 at 18:55
  • 2
    Works as advertised! – Doboy Sep 09 '16 at 17:24
6

This works in windows:

"C:\Program Files (x86)\Adobe\Adobe Photoshop CS5\Photoshop.exe" C:\completepathto\my.jsx

Pay attention to the path to Photoshop. It must be quoted since it contains spaces.

There are plenty of tricks for figuring out where Photoshop is loaded. Here is one that finds every location where Photoshop has been loaded and places those in x.lst

@REM  The Presets\Scripts doesn't really restrict where the loop is looking, 
@REM  thus the "IF EXIST" is needed.  The FIND makes sure that the 
@for /R "%ProgramFiles(x86)%\Adobe" %%f in (Presets\Scripts) 
  DO @IF EXIST %%f 
     (echo %%f | FIND /I "Adobe Photoshop C" >> x.lst )

You can then process each line in x.lst. NOTE: The entire "@for" should be on ONE line, I split it to multiple lines for readability.

If you believe there will be only one Photoshop (and not Elements) then you could change "echo %%f" to

"%%f\..\..\Photoshop.exe" C:\completepathto\my.jsx 
4

The straight answer is YES. Illustrator, InDesign and Photoshop can all be scripted through COM. Any program that you make that can access COM (such as a .net language, C++, BCX, Autohotkey or Powerpro) can tell Illustrator, InDesign or Photoshop to do things.

Here is an example for Powerpro(you will need powerpro's com plugin), and this works in CS4 and CS5:

Function ComLoad() ;;MAKE SURE TO CALL .@ComUnload WHEN EXITING FUNCTION CALLS!
      static objname="Illustrator.Application"
      static com_status, com_type
      static appRef=com.create_object(objname)
      endfunction

Function ComUnload();;this is end the com calls and unload com
    com.unload
    endfunction

After you use the ComLoad() function, you then run any kind of method or function offered by the COM library. Here is how to use Powerpro to tell Illustrator to run your jsx or js file:

;Run a script from anywhere
Function RunOtherScript(whatscript)
    If (file.Validpath(whatscript) == 0)do
        messagebox("ok","Whoops! That script doesn't exist!","ILL Runscript")
        quit
    endif
    .@ComLoad()
    appRef.DoJavaScriptFile(whatscript)
    .@ComUnload()
    quit

Here is an image of a floating toolbar that I made using Powerpro. The buttons are all attached to com functions. Most of the time I use the com functions to run external jsx scripts.

enter image description here

[edit]

There is another way! You can use the Adobe Configurator to create new panels which are capable of launching scripts. You can design the panel in any way you like, and the results are quite similar in effect to the powerpro toolbar I've described above. In fact, I moved from the powerpro toolbar to an Adobe Configurator Panel.

bgmCoder
  • 6,205
  • 8
  • 58
  • 105
  • 2
    But does that launch the Adobe apps when the COM is instantiated like manually opening the app and going through the script menu to execute the script but doing it programmatically? Or will this technique work GUI-lessly without the app GUI ever launching on the desktop? I noticed that for MS Office (at least earlier versions) would open the app like Word when COM was invoked and when done the GUI closes, so you briefly see it open to peform processing then close. I'd prefer a totally GUI-less option where possible. – David May 24 '13 at 00:01
  • Well, you will have to write code to decide what to do if the COM function is called without the adobe app having been previously started, and you'll need to do that before you begin the COM calls. However, what you can't do is to call a COM function to an Adobe app without that app's GUI being open. MS Office is a different tale in some cases. But if the Adobe app is open, you can make GUI-less COM calls to it, say, from another custom app; but again, the Adobe app's GUI will have to be open. I suppose you might be able to "hide" the app window or something... – bgmCoder May 26 '13 at 19:19
  • In the case I illustrated above, with my toolbar, since the toolbar only appears (thanks to powerpro!) when the Adobe app is open, I never have to worry about making sure the Adobe GUI is open before I run the COM scripts. – bgmCoder May 26 '13 at 19:28
  • AutoIt apparently also supports COM. I've used AutoIt; it is great, but I've never used the COM stuff with it. Might be worth looking at. – CRGreen Jul 08 '15 at 23:46
3

If you place the .jsx files in the right location

Photoshop
folder location:
/Applications/Adobe\ Photoshop\ CS5/Presets/Scripts
menu location:
File > Scripts

Illustrator
folder location:
/Applications/Adobe\ Illustrator\ CS5/Presets.localized/en_GB/Scripts
menu location:
File > Scripts

InDesign
folder location:
/Users/{user}/Library/Preferences/Adobe\ InDesign/Version\ 7.0/en_GB/Scripts/Scripts\ Panel
menu location:
Window > Utilities > Scripts

These are the paths on OSX, it should be easy to find the equivalent on Windows for Photoshop and Illustrator, but for InDesign it might be easier to open the Scripts Panel and open the scripts folder using the Panel's context menu.

I know that you can run .jsfl scripts from the command line by opening Flash and passing the path to the .jsfl script as an argument, but that doesn't seem to work for .jsx files with InDesign.

HTH

George Profenza
  • 50,687
  • 19
  • 144
  • 218
0

This question is quite old. I am going to answer this on the assumption that:

  1. You're running JSX scripts for after effects.
  2. You're using Windows.

I'm not sure whether you want to pass arguments to a script (in which case my simple solution won't work, or might need nasty workarounds).

Fortunately there is an easy way to do this with after effects. You can launch cmd and type the following command:

afterfx -r C:/Users/me/myscript.jsx

If afterfx isn't recognized, you'll need to add the after effects installation path to Path in your System Variables. I'm not aware of the availability of this feature in other Adobe programs. For more information about running your after effects scripts from the command line, you can consult: https://helpx.adobe.com/after-effects/using/scripts.html

-3

You can use extend script to run it . there is a free extension on creative cloud will help you to run scripts fast in illustrator , aftereffects, photoshop and premiere pro you can find it on adobe exchange ( liveview )

Fred
  • 1