Lisp HUG Maillist Archive

Using Lispworks open-pipe in windows

Hi all,

I have written a perl script that is running an infinite loop keeping
track of windows that come to the foreground (if anyone knows of a
good way to do this in LISP, I'd be thrilled).  I am working on
Windows XP.  When I run:

cmd /c "D:\get-next-window.pl" from the run menu, it works great.  It
opens up a DOS style window that shows the window handles of all the
windows as they come to the foreground.  When I run:

(sys:call-system "cmd /c D:\\Perl\\get- next-window.pl") it works
great.  It even works great when I use call-system-showing-output.
Both bring up the DOS style window with the correct output.

But, I need some way to keep a handle on the windows that are being
returned, so I'm trying to run it with:

(setf test (sys:open-pipe "cmd /c D:\\Perl\\get- next-window.pl")).

That doesn't seem to run well at all!  First of all, it creates a
process in my taskmgr called "perl.exe" that is taking up 99% of my
CPU cycles.  Nothing else can run while this is running.  Second, I
can't seem to read anything that's there.  (read-line test) just
hangs, and (read-char-no-hang test) returns NIL.

Does anyone know what is going on, and how to use open-pipe correctly
on windows?

If it matters, here's a copy of the perl script:

#!perl -w

use Win32::GuiTest qw{:ALL};
use FileHandle;
use strict;
use Socket;
use IO::Handle; # thousands of lines just for autoflush :-(
use IO::Select;

socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC )
                                or  die "socketpair: $!";

CHILD->autoflush(1);
PARENT->autoflush(1);

my @windows;
my $pid = fork();
my $gotit = 1;
my $selchild = IO::Select->new;
my $selstdin = IO::Select->new;
my @childhandle;
my @parenthandle;
my $timeout = .1;
my $input;

$selchild->add(\*CHILD);
$selstdin->add(\*STDIN);

if ($pid) {
   while (1) {
      my @foreground = GetForegroundWindow();

      if (grep {$_ eq $foreground[0]} @windows) {
         ; #do nothing
      } else {
         push(@windows, $foreground[0]);
         print "@windows\n";
      }

      if (@childhandle = $selchild->can_read($timeout)) {
         chomp(my $update = <CHILD>);
         print "Update = $update\n";
         $gotit = 0;
      }

      if ($gotit == 0) {
         my $winhandle = shift(@windows);
         print "$winhandle\n";
         $gotit = 1;
      }
   }

} else {

   while (1) {
         $input = <>;
         if ($input) {
            print PARENT $input;
         }
   }

Re: Using Lispworks open-pipe in windows

Disclaimer: I'm mostly a Linux guy.

On Tue, Dec 04, 2007 at 10:47:23AM -0600, Jordan Sanders wrote:
> I have written a perl script that is running an infinite loop
> keeping track of windows that come to the foreground (if anyone
> knows of a good way to do this in LISP, I'd be thrilled).  I am
> working on Windows XP.  When I run:
> 
> cmd /c "D:\get-next-window.pl" from the run menu, it works great.
> It opens up a DOS style window that shows the window handles of all
> the windows as they come to the foreground.  When I run:
> 
> (sys:call-system "cmd /c D:\\Perl\\get-next-window.pl") it works
> great.  It even works great when I use call-system-showing-output.
> Both bring up the DOS style window with the correct output.

That seems like a clue.  call-system-showing-output should show the
output of the Perl script in the Lispworks window, not in the DOS
window.  Your Perl script is not writing on the handle you think it's
writing on.

> But, I need some way to keep a handle on the windows that are being
> returned, so I'm trying to run it with:
> 
> (setf test (sys:open-pipe "cmd /c D:\\Perl\\get-next-window.pl")).

Not all that familiar with the ins and outs of running Perl on
Windows, but I'd think you'd want something more like

  (sys:open-pipe "perl c:\\Perl\\get-next-window.pl")

and leave cmd.exe out of the picture.

> That doesn't seem to run well at all!  First of all, it creates a
> process in my taskmgr called "perl.exe" that is taking up 99% of my
> CPU cycles.

Well, yeah.  The parent process in your Perl script has no sleeps or
(as near as I can tell) blocking IO.  So it'll happily use all the
CPU.  At very least throw a "sleep(0.1)" or something in the inner
loop.

> Does anyone know what is going on, and how to use open-pipe
> correctly on windows?

My guess is you should figure out what GetForegroundWindow does and
(if possible) rewrite it and the rest of your script in Lisp.  Failing
that, start much smaller: call this Perl script from Lisp

  print "Hello world";

and fiddle with that until you can read "Hello world" using
sys:open-pipe.  Then expand.

-- L


Updated at: 2020-12-10 08:44 UTC