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

OK... I've written a script that runs on win32 which takes some time to run. Instead of just leaving the screen blank, I wanted to show a text based progress indicator. The way I chose to do this is to show completed/total and update it on each iteration. Now the way I've gone about this seems rather hackish to me, but I couldn't find a better way. What I've actually done is print ^H's (One character, not two) to backspace over the previous display and then reprint. Here's the whole sub..
sub GetAgedComps { my $filter = FILTER_WORKSTATION_TRUST_ACCOUNT; my $level = 2; my $fudge = 120960; my $conversion = 86400; my ($server, $age, $silent) = @_; my (@machines, $comp, %info, %accts, $buf, $x); print " Pulling information from $server...\t\t" unless $silent; if (UserEnum($server, \@machines, $filter)) { print"[OK]\n" unless $silent; } else { print "[FAILED]\n" unless $silent; die " Unable to retreive information from $server: $!\n" } my $count = @machines; print " Checking for aged accounts...\t\t\t" unless $silent; foreach $comp (@machines) { unless ($silent) { $x++; #note, the funny char is a ^H print "" x length($buf) if $buf; print $buf = "[$x/$count]"; } unless (UserGetInfo($server, $comp, $level, \%info)) { die "\n Error retreiving information for $comp: $!\n"; } if (($info{'passwordAge'} - $fudge) / $conversion > $age ) { ($accts{$comp}) = int (($info{'passwordAge'} - $fudge) +/ $conversion); } } print "\n" unless $silent; return \%accts; }
Now my question is: is there a better way to do it? It works fine, but that doesn't mean that there isn't a more apropriate way to handle it.

Thanks,
Rich

PS - this pulls NT machine trust accounts that haven't been accesed in over a certian number of days. I was planning on posting it here once I have it cleaned up.

Replies are listed 'Best First'.
Re: Manipulating cursor position when printing to STDOUT
by bikeNomad (Priest) on Jul 16, 2001 at 19:30 UTC
    You can also use \r to back up over the whole line; this may actually be faster as it allows CMD to erase the line as a unit (you should time it).

    Or you could use ANSI escape sequences, but it would mean sending more characters.

      The Win32 console doesn't understand ANSI escape sequences. I don't know why that wasn't at least an option, since it was available on DOS (optional) and OS/2 (built in).

      If you use \r, make sure you print enough trailing spaces to erase what it said before.

Re: Manipulating cursor position when printing to STDOUT
by MZSanford (Curate) on Jul 16, 2001 at 19:35 UTC
    With NT, i would imagine most of the Term:: based solutions will not work, but i recall a Term::Progressbar (or something similar) that does pretty well. For NT, i have used either the backspace (^H or \b), but have also used the '.' style.

    using a '.', or any charachet, which is just printed for every X percent completed. And on the major percentages (25,50,75) i print the number. So, while it is not pretty, i've done the ^H more than once
    OH, a sarcasm detector, that’s really useful
Re: Manipulating cursor position when printing to STDOUT
by John M. Dlugosz (Monsignor) on Jul 17, 2001 at 01:52 UTC
    I've used a line of dots and \r in the recient past. For more elaborate work, you can control the cursor position by calling SetConsoleCursorPosition in the Win32 API.

    You can find this, and related function, in the Win32::Console perl module. I beleive this comes standard with ActiveState's build.

    —John