日付 | 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 - アプリケーション・バッチ・ショートカット・ファイルを開く