为什么使用Win32 :: Console在Perl中输入密码需要按两次Enter键?

时间:2012-06-27 00:45:06

标签: windows perl windows-console

我对Perl相当陌生,并且很难掌握以下密码输入代码段的行为:

use Win32::Console;

my $StdIn = new Win32::Console(STD_INPUT_HANDLE);
my $Password = "";

$StdIn->Mode(ENABLE_PROCESSED_INPUT());
local $| = 1;

print "Enter Password: ";
while (my $Data = $StdIn->InputChar(1)) {
    if ("\r" eq $Data ) {
        last;
    } 
    elsif ("\ch" eq $Data ) {
        if ( "" ne chop( $Password )) {
            print "\ch \ch";
        }
        next;
    }
    $Password .=$Data;
    print "*";
}

while (my $Data = $StdIn->InputChar(1)) {
    print "\nShow password? [y/n] ";
    if ("n" eq $Data) {
        last;
    }
    elsif ("y" eq $Data) {
        print "\nPassword: $Password\n";
        last;
    }
}

基本上会发生的事情是脚本提示用户输入密码并按预期显示每个字符输入*,但需要按 Enter 两次才能接受输入。但是,如果我删除第二个while循环(或用print $password语句替换),输入只需按一下 Enter

我还注意到在第二个while循环中,它提示用户输入 y n (无需按 Enter )如果用户输入'y',则在显示密码之前重复行Show password? [y/n]

对此行为的一些见解将不胜感激。

1 个答案:

答案 0 :(得分:3)

第一个 Enter 让您退出第一个while循环。然后第二个while循环在显示提示之前等待另一个字符。您应该在询问另一个角​​色之前显示提示(并且只显示一次)。

将事物分解为子例程有助于构建基本块。

use strict; use warnings;
use Win32::Console;

run();

sub run {
    my $StdIn = Win32::Console->new(STD_INPUT_HANDLE);
    $StdIn->Mode(ENABLE_PROCESSED_INPUT);

    my $Password = prompt_password($StdIn, "Enter Password: ", '*');

    if ( prompt_echo($StdIn, "\nShow password? [y/n] ") ) {
        print "\nPassword = $Password\n"
    }

    return;
}

sub prompt_password {
    my ($handle, $prompt, $mask) = @_;
    my ($Password);

    local $| = 1;
    print $prompt;

    $handle->Flush;

    while (my $Data = $handle->InputChar(1)) {
        last if "\r" eq $Data;

        if ("\ch" eq $Data ) {
            if ( "" ne chop( $Password )) {
                print "\ch \ch";
            }
            next;
        }

        $Password .= $Data;
        print $mask;
    }

    return $Password;
}

sub prompt_echo {
    my ($handle, $prompt) = @_;

    local $| = 1;
    print $prompt;
    $handle->Flush;

    while (my $Data = $handle->InputChar(1)) {
        return if "n" eq $Data;
        return 1 if "y" eq $Data;
    }

    return;
}