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

I have the following code, but can't seem to see anything other than the startup versioning information from diskpart when I print <OUT>. Do I have to flush after I print to the <IN> on Windows?

use FileHandle; use IPC::Open2; my $pid; eval { $pid = open2(\*OUT, \*IN, 'diskpart'); }; if ($@ and $@ =~ /^open2:/) { die "$@:$!\n"; } print IN "list disk"; close IN; while(<OUT>) { print "$line_no: $_"; $line_no++; } close OUT; exit(0);

So far all I get is this..

0:

1: Microsoft DiskPart version 6.0.6002

2: Copyright (C) 1999-2007 Microsoft Corporation.

3: On computer: HITAUTO-2008X86

4:

Replies are listed 'Best First'.
Re: open2 with windows diskpart
by ikegami (Patriarch) on Jun 16, 2009 at 23:57 UTC
    use IO::Handle qw( ); IN->autoflush(1);

    Wouldn't you need a newline too?

    print IN "list disk\n";
Re: open2 with windows diskpart
by BrowserUk (Patriarch) on Jun 17, 2009 at 00:05 UTC

    The problem is (almost certainly) that diskpart does direct console IO, rather than file IO to STDOUT. I haven't yet found a workaround for this.

    In theory, it should be possible to write an IPC::Open2-alike that uses Win32::Console (or better, the APIs that underlie that module), that would work regardless of the type of IO the child process uses.

    The reality is that it is rather harder to do than it should be.


    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.

      Hm. I've seen (and read) you post on this subject before.. I'm in this lousy situation where I must interact with diskpart to select, then list, then select, then list...etc. The select actions are dependent on the list of course. I know of no other way to interact with diskpart other than open2. Do you?

Re: open2 with windows diskpart
by ikegami (Patriarch) on Jun 17, 2009 at 00:11 UTC

    You're going through a lot of trouble to ignore exceptions that don't even exist.

    my $pid; eval { $pid = open2(\*OUT, \*IN, 'diskpart'); }; if ($@ and $@ =~ /^open2:/) { die "$@:$!\n"; }

    should be

    my $pid = open2(\*OUT, \*IN, 'diskpart');

    $! is already included in the error message if appropriate. Even in some situations where it's not. (Perl RT66572)

      I think autoflush is set to true by default, and you are probably right about me checking for too many errors. Other than those items, were you able to get the snippet to function on Windows with diskpart?

        Worked fine for me simply by adding the missing "\n" I mentioned.

        I had problem detecting the prompt because it's not sent until the line is ended (which doesn't happen until someone types since the output appears to be line buffered). I solved that by forcing the prompt to show up twice.

        use strict; use warnings; use IO::Handle qw( ); use IPC::Open2 qw( open2 ); sub wait_for_prompt { my ($to_chld, $fr_chld) = @_; # Force two prompts to appear. print $to_chld "\n"; my $count; while (<$fr_chld>) { print "$.: $_"; last if /^DISKPART> $/ && ++$count == 2; } } { my $pid = open2(my $fr_chld, my $to_chld, 'diskpart'); #print $to_chld "\n"; #wait_for_prompt($to_chld, $fr_chld); print $to_chld "list disk\n"; wait_for_prompt($to_chld, $fr_chld); print $to_chld "exit\n"; wait_for_prompt($to_chld, $fr_chld); close $to_chld; waitpid($pid, 0); }