IPC :: Open3. Solving the problem with STDERR

    When we write a graphical application, it happens that you need to call external programs and read from STDOUT / STDERR.
    The IPC :: Open3 module does an excellent job of this .

    However, the program you wrote, everything works, but you do not want the user (or you) to see an unnecessary terminal window.

    There are several options to hide it:

    1. Run the script through wperl.exe, and not through perl.exe
    2. ???

    Consider the program
    use strict;
    use Tkx;
    use IPC :: Open3;
    my $ mw = Tkx :: widget-> new ('.');
    my $ tw = $ mw-> new_text ();
    my $ 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;
    


    image

    The dir command is called, and its result is displayed. (ignore the encoding).

    Everything works, but if you run the script through wperl.exe, then when you call open3 you get an error:
    open3: Can't call method "close" on an undefined value at C: /perl5.8/lib/IPC/Open3.pm line 368.
    open3: Can't call method "close" on an undefined value at C: /perl5.8/lib/IPC/Open3.pm line 368.
    


    The problem is that wperl does not create standard threads (STDIN, STDOUT, STDERR).

    I puzzled for a long time how to make the program work. I tried to call WINAPI inside the body of the program, run the file via bat (it works, but not with all programs), but the solution turned out to be a simple surprise.

    You must use the ShellExecute function from shell32.dll with the SW_HIDE attribute.

    Below is the loader code in C.
    #include 
    #include 
    static char * ldr_file = "app.pl";
    static char * ldr_path = "";
    int main (int argc, char * argv [])
    {
      int code;
      LoadLibrary ("shell32.dll");
      code = (int) ShellExecute (NULL, "open", ldr_file, ldr_path, NULL, SW_HIDE);
      if (code <= 32)
      {
    	char buf [200];
    	sprintf (buf, "Cannot run application. Code:% d", code);
    	MessageBox (
    		NULL
    		buf
    		"Dynld Error",
    		MB_ICONERROR | MB_OK
    	);
      }
      return code;
    }
    


    Compile gcc from MinGW.
    gcc -mwindows loader.c -o loader.exe


    Also popular now: