Photoshopのスクリプトjsxでアプリを実行する方法


たまーに、何を思ったのか、
突然思い出したかのようにテック系のメモを残すのだけど
今年もその時期が来たようだw
ハレー彗星かよw

ではでは早速。
表題通り、

photoshopスクリプトjsxでアプリを実行する方法。

なぜ?Photoshopからほかのアプリを立ち上げるの?
それは、photoshpoの画像処理だけでは、どうにも遅い場合や
非同期で画像処理を実行したい場合、photoshopだけでは限界があるから。

バッチ処理で画像のサイズを変える処理を実行させるよりも、
画像サイズを調整するコンソールアプリを用意しておき、
バックグラウンドでアプリを実行させたほうが速い。

ほかにもphotoshopではできない特殊な処理を行う場合も
バックグラウンドでコンソールアプリを実行させてやればOK。
例えばかなり特殊な画像フォーマットへの圧縮とか。

使いどころはいろいろあるわけですな。
色々と調べてみたところ方法は2つほど。

シンプルな方法はapp.system

こんな感じ

cmd = [
    "help dir\npause"
]
var ret = app.system(cmd.join(" "));

上記はDosだけど例えば・・・

cmd = [
    "C:\Windows\System32\notepad.exe",
    "D:\Test.txt"
]
var ret = app.system(cmd.join(" "));

こんな感じで引数付きでアプリを起動できる。

メリット。
簡単、手っ取り早い。

デメリット。
同期実行なので実行中のアプリが終了するまで処理が終わらない。
日本語を含むパスに注意!
日本語パスが含まれる場合はjsxファイルをshift-jisにする必要がある。
GUIを隠す方法がない。
リターンが拾えない。

ちなみに・・・、
AfterEffectsの場合は

var ret = system.callSystem(cmd.join(" "));

のような実行方法がある。
こっちは非同期実行。
このあたりの仕様統一しておけよな・・・。

file.executeをつかう

こんな感じ

var cmd = "C:\Windows\System32\notepad.exe";
var fobj = new File(cmd);
var ret = fobj.execute();

ただこれでは、どうも引数が渡せないっぽい。
なので少し工夫する。

function writeVBSFile(source)
{
    var stdout = "";
    var vbs = new File(Folder.temp + "/temp.vbs");
    var ret = vbs.open ("w")
    if (ret)
    {
        vbs.write(source);
        vbs.close();
    }
    return vbs;
}

var s = [
    "Dim wsh",
    "Set wsh = CreateObject(\"WScript.Shell\")",
    "wsh.Run \"C:\\Windows\\System32\\notepad.exe D:\\Test.txt\", 1, False"
]

var vbs = writeVBSFile(s.join("\n"))
var fobj = new File(vbs);
var ret = fobj.execute();

上記ではとりあえず、vbsを使っているけれど
ランタイムが入っている環境であれば
python でも js でもなんだってかまわない。

wshの場合は、最後の引数を 0, False に変更すればGUIも隠して実行できる。
完全にバックグラウンドで処理できる。

メリット。
非同期実行が可能。
GUIを完全に隠せる。
pythonでもjsでもランタイムさえあれば何でも行ける。
勝手にshift-jisで保存されるので日本語パス問題は気にしなくても大丈夫そう。

デメリット。
書き方が(ちょっと)面倒。
リターンが拾えない。

ちなみに、
非同期で実行したアプリの終了を調べるなら、
手っ取り早くtaskコマンドで調べるか、
またはアプリの終了時に終了を知らせる様に適当に何かを仕込んでおくか。

そのあたりはお好きに。

どのみちリターンは拾えない

どっちの方法も実行が成功したか失敗したか?は拾えるけれど、
アプリ自身のリターン値をstdoutのような感じで拾うことができない。

なので、リターンをどこかにファイルで保存しておき、それをstring値で読み込み。
eval(<任意の文字列>) で評価するとか。
そうなると、適当なパーサーが必要になるかな・・・。

もうちょっと、賢い方法が何かあると思うけれど・・・。

AfterEffectsの場合はリターンがちゃんと拾えるので

var ret = system.callSystem(cmd.join(" "));
ret.split("\r\n");

とすればOK。

このあたり、同じjsxでも仕様が違う。
なんだよこのポンコツ仕様。

MACで同じことをどうやるのかは、そもそもMAC持ってないので調べてないです。
すんません。

そういえばGUIがHTML5で作れるCCシリーズは今どんな感じなんだろう。
CCシリーズのバックグラウンドで動いているCEPエンジン。
これがまたポンコツで、結構実装されてないことがあったんだけど、
今はどうなんだろう?改善したのかな?

ということで、今日のメモでした~。

Leave a comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください