IPC :: Open3。 STDERRで問題を解決する

グラフィカルアプリケーションを作成する場合、外部プログラムを呼び出してSTDOUT / STDERRから読み取る必要が生じることがあります。
IPC :: Open3モジュールは、 これについて素晴らしい仕事をます。

ただし、作成したプログラムはすべて機能しますが、ユーザー(またはユーザー)に不要なターミナルウィンドウを表示させたくありません。

非表示にするオプションがいくつかあります。

1. perl.exeではなくwperl.exeを使用してスクリプトを実行します
2. ???

プログラムを検討する
厳格な使用;

 Tkxを使用します。
 use IPC :: Open3;

 my $ mw = Tkx :: widget-> new( '。');
私の$ tw = $ mw-> new_text();

私の$ bt = $ mw-> new_ttk__button(
     -text => 'dir'、
     -command => sub {
         my($ rdr、$ pid);
         $ pid = open3(undef、$ rdr、undef、 'dir');
         $ tw-> insert( 'end'、do {local $ /; <$ rdr>});
     }、
 );

 Tkx :: pack($ tw);
 Tkx :: pack($ bt);

 Tkx :: MainLoop;


画像

dirコマンドが呼び出され、その結果が表示されます。 (エンコードを無視します)。

すべて動作しますが、wperl.exeを使用してスクリプトを実行すると、open3を呼び出すとエラーが発生します。
 open3:C:/perl5.8/lib/IPC/Open3.pm行368の未定義の値に対してメソッド「close」を呼び出すことはできません。

 open3:C:/perl5.8/lib/IPC/Open3.pm行368の未定義の値に対してメソッド「close」を呼び出すことはできません。


問題は、wperlが標準スレッド (STDIN、STDOUT、STDERR)を作成しないことです。

私は長い間、プログラムを機能させる方法に戸惑いました。 プログラムの本体内でWINAPIを呼び出し、batを介してファイルを実行しようとしましたが(すべてのプログラムで機能するわけではありません)、解決策は簡単な驚きでした。

SW_HIDE属性を使用してshell32.dllのShellExecute関数を使用する必要があります。

以下はCのローダーコードです。
 #include <stdio.h>
 #include <windows.h>

 static char * ldr_file = "app.pl";
 static char * ldr_path = "";

 int main(int argc、char * argv [])
 {
   intコード;
   LoadLibrary( "shell32.dll");
  
   code =(int)ShellExecute(NULL、 "open"、ldr_file、ldr_path、NULL、SW_HIDE);
   if(コード<= 32)
   {
	 char buf [200];
	 sprintf(buf、「アプリケーションを実行できません。コード:%d」、コード);
	 MessageBox(
		 NULL
		バフ
		 「Dynld Error」、
		 MB_ICONERROR |  MB_OK
	 );
   }

  リターンコード;
 }


MinGWからgccをコンパイルします。
gcc -mwindows loader.c -o loader.exe

Source: https://habr.com/ru/post/J67712/


All Articles