ブログ

ご注意:
この情報は過去に書かれたブログ記事のキャッシュになります。最新の情報ではありませんのでご注意ください。
また、公開当時のキャッシュされたテキストのみを読めるようにした内容になっております。 公開当時の画像やデザイン情報がありませんので、デザイン上読みにくい部分がありますことをご了承ください。 なお、最新のブログはGitHubにて公開しています。

日付0000/00/00

LAUNCH EXTERNAL PROCESSは,外部プログラムを実行するためのコマンドです。ウィンドウアプリケーションを起動することもできますが,コンソールアプリケーションを外部プロセスで起動するのが一般的です。ウィンドウアプリケーションを起動するのであれば,通常,Open (Mac) やCMD.exe (Windows) のStartコマンドを経由します。起動したコマンドラインアプリケーションから出力 (stdIn, stdErr) は,コマンドの第3, 第4パラメーターにテキストまたはBLOBで返されますが,Windowsの場合,CMD.exeのリダイレクト (>) 指定により,これを外部ファイルに書き出すこともできます。この記事では,LAUNCH EXTERNAL PROCESSの出力をリダイレクトさせる方法を説明しています。


CMD.exe: 初期メッセージの抑制

LAUNCH EXTERNAL PROCESSの第1パラメーターには,実行したいプログラムのパスと引数を文字列で渡します。 CMD.exeのサーチパスは,環境変数PATHに含まれているので,コマンド名だけでじゅうぶんです。カレントディレクトリは,SET ENVIRONMENT VARIABLEで指定することができます。

しかし,たとえば,再帰的にディレクトリのリストを取得するDirをコールするために,下記のようなメソッドを記述しても,有効な情報は何も返されません。

$directory:=System folder(Desktop)

SET ENVIRONMENT VARIABLE \
("_4D_OPTION_CURRENT_DIRECTORY";$directory)
$command:="cmd.exe dir"
C_TEXT($stdIn;$stdOut;$stdErr)
LAUNCH EXTERNAL PROCESS($command;$stdIn;$stdOut;$stdErr)

CMD.exeは,対話型のコンソールアプリケーションなので,起動直後の初期メッセージを表示したところで停止します。すぐに特定のコマンドを実行させたいのであれば,/cまたは/kオプションを渡さなければなりません。たとえば,下記のように記述することができます。

$command:="cmd.exe /c dir /s /b > "+"log.txt"

ウィンドウの抑制

LAUNCH EXTERNAL PROCESSは,特に何も指定しなければ,コンソールウィンドウを表示するようになっています。これを抑制するためには,やはり,SET ENVIRONMENT VARIABLEを使用します。さらに,起動したプロセスの終了を待たずに,メソッドの実行を続けることもできます。その場合,stdOut, stdErrには何も返されません。

SET ENVIRONMENT VARIABLE \
("_4D_OPTION_HIDE_CONSOLE";"true")
SET ENVIRONMENT VARIABLE \
("_4D_OPTION_BLOCKING_EXTERNAL_PROCESS";"false")

$command:="cmd.exe /c dir /s /b > "+"log.txt"
LAUNCH EXTERNAL PROCESS($command)

パスのエスケープ

CMD.exeのコールで厄介なのは,パスや引数のエスケープです。スペースが含まれるような単純な文字列であれば,ダブルクオートで引用するだけで良いかもしれませんが,値に引用符が含まれるのであれば,バックスラッシュでエスケープする必要があります。しかし,引用を閉じるダブルクオート,つまり最後の引用符は,エスケープしてはいけません。その上,CMD.exe特有のメタ文字《(, ), %, !, ^, ", <, >, &, |》も考慮する必要があります。たとえば,下記のような処理をしなければならない,ということです。

C_TEXT($1;$0;$param)

$param:=$1

C_LONGINT($platform;$i;$len)
PLATFORM PROPERTIES($platform)

If ($platform=Windows)
$shoudQuote:=False
$metacharacters:="&|<>()%^\" "
$len:=Length($metacharacters)

For ($i;1;$len)
$metacharacter:=Substring($metacharacters;$i;1)
$shoudQuote:=$shoudQuote | (Position($metacharacter;$param;*)#0)
If ($shoudQuote)
$i:=$len
End if
End for
If ($shoudQuote)
If (Substring($param;Length($param))="\\")
$param:="\""+$param+"\\\""
Else
$param:="\""+$param+"\""
End if
End if
End if

$0:=$param

参考記事:

Everyone quotes command line arguments the wrong way

GitHubには,LAUNCH EXTERNAL PROCESSの例題がいくつか公開されています。


poppler - PDFのページ結合/分離・文字列の取り出し


7-zip - ファイル/フォルダフォルダの圧縮と展開


sublaunch - アプリケーション・バッチ・ショートカット・ファイルを開く