从ExtendScript之外执行JSX脚本是否可行?

33

一般情况下,当你编写一个.jsx脚本来自动化Adobe产品(如InDesign、Illustrator或Photoshop)时,你需要在ExtendScript IDE中编写、调试和执行脚本。是否可以绕过ExtendScript并从第三方程序运行脚本?

我认为Adobe产品有内置的JavaScript解释器,ExtendScript可以连接到该解释器以访问Adobe对象模型并自动化其软件。我希望能够直接连接到该解释器并像在ExtendScript中一样运行jsx文件。

7个回答

37

你是在使用Mac电脑吗?如果是,你可以使用AppleScript和osascript工具来执行JavaScript。以下是一些示例:

运行JSX并返回值

将以下内容保存为~/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

将此保存为~/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;

现在,从命令行运行osascript ~/temp/foo.scpt。它将打印活动Illustrator文档中的图层数。

从JavaScript中获取数据是有限制的。您无法从JavaScript中打印到stdout。相反,将要返回的值作为JSX文件的最后一条语句放置;它将被osascript打印出来。(原因在于:JSX文件中的最后一个值是do javascript AppleScript语句的返回值。这也是AppleScript文件中的最后一个值,并且osascript会打印最终值。)

您从JavaScript返回的值可以是数字、字符串、数组或任何其他在转换为字符串时保留其值的对象。如果您想返回复杂对象,则需要#include一个JSON库并在对象上调用.toJSONString()

向JSX传递参数

要向JSX代码传递参数,请按照以下示例操作:

文件~/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

文件 ~/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]);
}

然后运行osascript args.scpt 50 30 10 80

调试

do javascript命令还有启动ExtendScript调试器的选项。有关详细信息,请在AppleScript编辑器中打开Illustrator字典。


3
Windows 怎么办?你有什么想法吗? - David
这是如何运行文件目录的代码: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
@David,请查看我针对Windows的答案。 - jfizz
我不得不将 do javascript "..." 更改为 do script "..." language javascript - crishoj
这是我在jasminejsx中使用JXA到JSX的方法。https://github.com/theasci/jasminejsx/blob/ff5f6e5/run.sh#L11 - spyle
显示剩余3条评论

16

对于Windows用户,您可以使用vbs脚本。通过向cscript命令提供参数来将参数传递给.jsx脚本,例如: cscript test.vbs "hello"。test.vbs可能看起来像这样:

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)

Wscript.Echo会返回.jsx文件中最后一行的内容。.jsx文件示例:

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

运行时,您应该会在Illustrator(或其他Adobe程序)中看到“hello”警报,然后将“test”返回到stdout(您应该在命令提示符窗口中看到它)。


1
对于那些喜欢坚持使用所有JavaScript的人,这里的解决方案可以重新编写为Microsoft JScript。然后它将成为JavaScript的一个版本(可以执行ActiveX/COM调用),以执行实际的JSX JavaScript代码。 - David
2
如果您安装了多个版本的Adobe应用程序,请使用Illustrator.Application.xx,其中xx是版本号(十进制),以获取您想要的版本。 - C.O.
如果您正在运行 Windows x64 并且想要使用 Photoshop 的 32 位版本,例如使用批处理文件来运行以下内容的示例脚本:START C:\Windows\SysWOW64\cmd.exe /K "cscript test.vbs hello" - C.O.
2
如广告所述,工作正常! - Doboy

6

这在Windows中有效:

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

注意Photoshop的路径。由于包含空格,必须加引号。

有很多技巧可以找出Photoshop加载的位置。以下是一种方法,它会查找Photoshop已加载的每个位置,并将这些位置放在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 )

你可以处理x.lst中的每一行。注意:整个“@for”应该在一行上,我将其拆分成多行以提高可读性。
如果你认为只会有一个Photoshop(而不是Elements),那么你可以将"echo %%f"更改为
"%%f\..\..\Photoshop.exe" C:\completepathto\my.jsx 

你能否以这种方式将脚本参数传递给JSX文件,作为脚本路径后Photoshop的附加参数? - David
我想知道是否在 Mac 上可以使用类似的方法,例如:/pathOnMacTo/Photoshop /completePathTo/my.jsx。 - David
@David:回复晚了,但是是的,在OSX上同样的方法也适用。 - Steven the Easily Amused

4
直截了当的回答是是的。Illustrator、InDesign和Photoshop都可以通过COM进行脚本编写。任何能够访问COM的程序(例如.net语言、C++、BCX、Autohotkey或Powerpro)都可以告诉Illustrator、InDesign或Photoshop执行操作。
以下是一个示例,使用Powerpro(您需要安装Powerpro的COM插件),该示例适用于CS4和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

在使用ComLoad()函数后,您可以运行COM库提供的任何类型的方法或函数。以下是如何使用Powerpro告诉Illustrator运行您的jsx或js文件:

;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

这是我用Powerpro制作的浮动工具栏的图片。按钮都附加到了com函数上。大部分时间,我使用com函数运行外部jsx脚本。 enter image description here [编辑]
还有一种方法!您可以使用Adobe Configurator创建新的面板,这些面板可以启动脚本。您可以以任何喜欢的方式设计面板,效果与上述powerpro工具栏非常相似。实际上,我从powerpro工具栏转移到了Adobe Configurator面板。

2
但是,当COM被实例化时,是否会启动Adobe应用程序,就像手动打开应用程序并通过脚本菜单执行脚本一样,但是以编程方式执行?还是这种技术可以在没有应用程序GUI启动的情况下无需GUI工作?我注意到对于MS Office(至少早期版本),当调用COM时会打开应用程序,例如Word,处理完成后GUI关闭,因此您会短暂地看到它打开以执行处理,然后关闭。如果可能的话,我更喜欢完全无GUI选项。 - David
你需要编写代码来决定在启动COM调用之前,如果没有先启动Adobe应用程序该怎么办,但你无法在Adobe应用程序的GUI未打开的情况下调用COM函数。在某些情况下,MS Office则不同。但是,如果Adobe应用程序已打开,你可以对其进行无GUI COM调用,例如从另一个自定义应用程序;但是,Adobe应用程序的GUI必须打开。我想你可以尝试“隐藏”应用程序窗口或其他方法... - bgmCoder
在我上面举的例子中,由于我的工具栏只有在Adobe应用程序打开时才会出现(感谢PowerPro!),因此在运行COM脚本之前,我永远不必担心确保Adobe GUI已经打开。 - bgmCoder
AutoIt 显然也支持 COM。我用过 AutoIt;它很棒,但我从未使用过其中的 COM 部分。也许值得一看。 - CRGreen

3
如果您将.jsx文件放在正确的位置
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

这些是在OSX上的路径,对于Photoshop和Illustrator应该很容易找到Windows上的等效路径,但对于InDesign来说,通过打开脚本面板并使用面板上下文菜单打开脚本文件夹可能更容易。

我知道你可以通过打开Flash并将.jsfl脚本的路径作为参数传递来从命令行运行脚本,但似乎对于InDesign中的.jsx文件不起作用。

希望对你有所帮助。


有趣。谢谢你,乔治。 - Thomas
不幸的是,“正确位置”随着Adobe产品的每次新安装或更新而改变。例如,这些评论非常陈旧,因为CS5现在已经“很久以前”的事了。 - Steven the Easily Amused
CC路径看起来很相似:/Adobe Illustrator CC/en_US/Scripts - George Profenza

0

这个问题很旧了。我假设:

  1. 您正在运行 After Effects 的 JSX 脚本。
  2. 您使用的是 Windows 操作系统。

我不确定您是否想要向脚本传递参数(这种情况下,我的简单解决方案将不起作用,或者可能需要一些恶心的解决方法)。

幸运的是,After Effects 有一个简单的方法来实现这一点。您可以启动 cmd 并键入以下命令:

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

如果无法识别afterfx,则需要将After Effects安装路径添加到系统变量中的Path。我不知道其他Adobe程序是否具有此功能。 有关从命令行运行After Effects脚本的更多信息,请参阅:https://helpx.adobe.com/after-effects/using/scripts.html

-3

您可以使用Extend Script来运行它。 在创意云上有一个免费的扩展程序,可以帮助您在Illustrator、After Effects、Photoshop和Premiere Pro中快速运行脚本。 您可以在Adobe Exchange(liveview)上找到它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接