in reply to Re: Recovering From Win32::Console
in thread Recovering From Win32::Console

I wondered about the need for a code snipppet.

Term::ReadKeywouldn't load on my system. Something about missing terminators or something.

Anyway, here's the code:

#!/usr/bin/perl use strict; use Win32::Console; my $usrnam = get_username(); my $usrpwd = get_password(); while (1) { my $inpflg = 0; my $geninp; while (!$inpflg) { print "Command: "; chomp ($geninp = <STDIN>); my $tstinp = $geninp; $tstinp =~ s/^\s+//g; $tstinp =~ s/\s+$//g; if ($tstinp ne '') { $inpflg = 1; } } if ($geninp =~ /exit/) { exit; } elsif ($geninp =~ /go/) { print "Username: $usrnam\n"; print "Password: $usrpwd\m"; } } sub getpass() { # Establish a console control object my $cnsbuf; # our $cnsbuf; if (!$cnsbuf) { $cnsbuf = new Win32::Console(STD_INPUT_HANDLE); } if (!$cnsbuf) { return(undef); } # Ensure console ECHO is OFF my $oldmod = $cnsbuf->Mode(); if ($oldmod & ENABLE_ECHO_INPUT) { my $newmod = ($oldmod ^ ENABLE_ECHO_INPUT); $cnsbuf->Mode($newmod); } # Go get the password my $usrpas = <STDIN>; chomp($usrpas); # Return console to old mode $cnsbuf->Mode($oldmod); # Print the missing newline print "\n"; # Give 'em what they asked for return($usrpas); } sub get_username() { print "Username: "; chomp (my $wrknam = <STDIN>); return $wrknam; } sub get_password() { print "Password: "; chomp (my $wrkpas = &getpass()); return $wrkpas; }

If you change the "my $cnsbuf;"to "our $cnsbuf;"the wild-n-crazy console problem will go away.

Replies are listed 'Best First'.
Re: Re: Re: Recovering From Win32::Console
by BrowserUk (Patriarch) on Jun 05, 2003 at 22:58 UTC

    I think what your doing is fraught with problems. Using console IO and stdio on the same handle is much like using sysread and friends alongside <READ> on the same filehandle; it may work some of the time, but the interaction between the two modes of operation will eventualy conflict and produce undefined (and possibly undefinable) results. That's not to say you couldn't make it work, but your unlikely to get much support doing so.

    The Console api's allow a process to effectively have multiple consoles. When you create a new console specifying one of the standard handles, you are effectively tying that handle to the Console api's. As you haven't specified any modes, you are getting

    GENERIC_READ | GENERIC_WRITE | FILE_SHARE_READ | FILE_SHARE_WRITE by default.

    Once you so tie the handle to a console, unless you take steps to untie it, when the console handle goes out of scope, the handle is effectively thrown away (read:closed), hence why making the handle global with our delays the onset of the problem.

    I really think that unless you intend using the Console Api's for all your terminal IO, then you would save yourself a lot of grief by solving your problems with Term::ReadKey. Mixing API's the way you are is only likely to lead to more frustration.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller