rgaddi has asked for the wisdom of the Perl Monks concerning the following question:

This can't be as difficult as I'm making it out to be. I'm trying to write a wrapper around 'aspell -c', which takes a filename, opens the file interactively in the console to be spell checked, and saves the changes back to the file. What I want to do is, in short: And here's what I've been trying.
# Create a temporary file to hold the input. my ($fh, $filename) = tempfile(); # And stream everything into it. my $linecount = 0; while (<>) { $fh->print($_); $linecount++; } print STDERR "Wrote $linecount lines to $filename.\n"; # Now pass the input off to aspell for processing my $obj; my $appname = "C:\\Program Files\\Aspell\\bin\\aspell.exe"; my $cmdline = "--check $filename"; my $iflags = 0; my $cflags = NORMAL_PRIORITY_CLASS + CREATE_NEW_CONSOLE; my $curdir = "."; Win32::Process::Create( $obj, $appname, $cmdline, $iflags, $cflags, $curdir) or die "Couldn't shell to aspell.\n"; $obj->Wait(INFINITE); # Return the tempfile on standard output seek($fh, 0, 0); while (<$fh>) { print }
Any thoughts on what I'm doing wrong?

Replies are listed 'Best First'.
Re: Shelling a new process with console I/O in Windows
by bellaire (Hermit) on Mar 10, 2009 at 18:04 UTC
    I think you forgot to tell us in detail what problems you're having. Please don't ask me to download your source, run it, and debug it all on my own in order to help you.

    What happens when you run your script? How is that different from what you want to have happen?
Re: Shelling a new process with console I/O in Windows
by Bloodnok (Vicar) on Mar 10, 2009 at 18:08 UTC
    In order for us to attempt to determine what you're doing wrong, you need to tell us what is not going right - all you've succeeded in doing thus far is to outline the context of the problem, but not what the problem itself is (as far as you can tell)...

    A user level that continues to overstate my experience :-))
Re: Shelling a new process with console I/O in Windows
by admiral_grinder (Pilgrim) on Mar 10, 2009 at 18:46 UTC
    I agree with the others, need more data. However, something that looked funny to me is your Create() call. I believe that $cmdline needs to include $appname with it.
Re: Shelling a new process with console I/O in Windows
by Anonymous Monk on Mar 10, 2009 at 21:08 UTC
    D'oh! This is true, problem is lacking in problem. The problem is that I'm not getting a new console window for the shelled program. Everything's staying in the original console (which I care less about), and more to the point not turning STDIN back over to the keyboard, which makes interactive programs like aspell much harder to use. This means that "perl -w aspell_filter.pl README.TXT" works just fine, but "type README.TXT | perl -w aspell_filter.pl" doesn't. The latter is, unfortunately, the whole reason for putting this together in the first place. I've taken the variable of aspell out of the mix by replacing the call with CMD.EXE for now, just to see what's going on. Here's the entire program again, with the changes, and all of the initial 'use's.
    use strict; use IO::File; use File::Temp qw(tempfile); use Win32::Process; use Win32; # Create a temporary file to hold the input. my ($fh, $filename) = tempfile(); # And stream everything into it. my $linecount = 0; while (<>) { $fh->print($_); $linecount++; } print STDERR "Wrote $linecount lines to $filename.\n"; # Now pass the input off to aspell for processing my $obj; my $appname = "C:\\windows\\system32\\cmd.exe"; my $cmdline = "/K dir"; my $iflags = 0; my $cflags = NORMAL_PRIORITY_CLASS + CREATE_NEW_CONSOLE; my $curdir = "."; Win32::Process::Create( $obj, $appname, $cmdline, $iflags, $cflags, $curdir) or die "Couldn't shell to aspell.\n"; $obj->Wait(INFINITE); # Return the tempfile on standard output seek($fh, 0, 0); while (<$fh>) { print } print "Check complete."
    Sorry for the initial screwup. Anyone got any thoughts? I'm not tied to the idea of a second console, or using Win32::Process directly, I'm just looking for the moral equivalent of:
    STDIN = console input; STDOUT = console display; system("stuff"); STDOUT = back to the redirected version;

      There is still no clear explanation of what exactly you are trying to achieve with your code? Rather than posting more code, please try to explain what it is that you are trying to achieve.

      For example, one reading of the words you've posted so far is that you want to:

      1. start an executable from a perl program, passing it a filename via the command line;
      2. Allow the user to interact with that program via the console;
      3. Have the perl script capture the output from the program;
      4. Then print that output on the (same?) console.

      But if that is a correct reading, I cannot see how you thought the code you've posted so far was ever going to acheive that--so, perhaps I mis-reading the words?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Shelling a new process with console I/O in Windows
by furry_marmot (Pilgrim) on Mar 11, 2009 at 19:00 UTC

    Dude,

    This is some weird stuff. It looks like you're spell-checking a tempfile. Doesn't aspell make a backup after it's done?

    Anyway, if you change " + CREATE_NEW_CONSOLE" to " | CREATE_NEW_CONSOLE", it should work fine.

    BTW, if the original window is supposed to wait for aspell to finish anyway, why not just do this:
    system('C:/Program Files/Aspell/bin/aspell.exe', '--check', "$filename +");
      Yep, that was it. The entire point was to be able to wrap the interactive version of aspell in a pipeline, i.e.
      head filename | perl aspell_filter.pl | sort
      or some such nonsense. The reason behind all of this is that the email client I'm trying to use these days for various reasons, Claws Mail, doesn't have a built-in spell checker on the Windows port. It does, however, have the ability to pipe all of the text of the email being worked on to the standard input of another program, then replace that email text with whatever comes out of the standard output. Hence the need for a wrapper to allow me to take in STDIN, work with it via console+keyboard, and pipe the results back out STDOUT. The hope was to be able to throw something together quick and dirty in 20 lines and be done with it. The reality has been anything but, and I think I'm on the verge of abandoning the project. furry_marmot's tip solved the immediate problem; I can now embed the program in a pipeline and it pops up a new console and works beautifully. But it's still not working from Claws, nor is
      print "Results are:\n"; while (<>) { print; }
      Leading me to believe that Claws's pipeline features are broken under Windows as well, thus defeating the point of the project. Still, thanks for the help. I'm sure I'll wind up needing that trick again at some point.
      change " + CREATE_NEW_CONSOLE" to " | CREATE_NEW_CONSOLE", it should work fine.
      That really shoudn't make any difference. The result would only be different if there were some bits in common between the two constants being added/orred.

      However, there couldn't be any bits in common, because otherwise the function being called couldn't work out a specific meaning for a bit being set.

      That aside, good call on using system() :-)

      --
      use JAPH;
      print JAPH::asString();

        It shouldn't make a difference, but it does. The first way doesn't work. Windows documentation says to use the pipe character, so I just always do.

        Anyway, thanks!