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

I am running ActiveState Perl 5.22 on Windows 10. I am running a Perl program from a Windows command prompt that has both user input from a keyboard, and subsequent output to the screen as the program runs. I want to capture BOTH the input and output to a log file. I have found several ways to capture the output to a file, but can't seem to capture the input. Here is a simple example:
print "\nHow old are you?: "; $age = <STDIN>; $year = 2017 - $age; print "You were born in $year\n"
resulting in:
How old are you?: 50 You were born in 1967
I can't seem to find a way get the "50" to show up in a log file. The old "script" utility on Unix captured everything that happened in a terminal, but I can't seem to find a Windows command prompt equivalent either. Any ideas? Thanks.

Replies are listed 'Best First'.
Re: Saving a Perl session to a file
by AnomalousMonk (Archbishop) on Apr 14, 2017 at 02:57 UTC

    Update: Caution: This is only tested under Windows 7!

    Play around with Win32::Console. This script
    Script: cap_con_1.pl

    Captures:

    Update: Use cls to begin a "session". You should be able to futz around with the captured  $rect string to clip off the invocation of the script at the end. Also, the Perl script can be converted into a  .bat file with the venerable Windows Batch Wrapper trick:
    File: capsess.bat

    Session: Caution: This is only tested under Windows 7!


    Give a man a fish:  <%-{-{-{-<

      very nice indeed.. but i've a problem with this: if i understand the captured rectangle contains everything was on the screen before the capture script was launched but when your program emits it's output i get the whole text in vertical sense ie only in the first column of the console.

      Can be related to the following regexes (which i do not understand)?

      $rect =~ s{ \0\a\0 } ''xmsg; $rect =~ s{ [ ]+ \z } ''xms; $rect =~ s{ .{$width} \z } ''xms;

      Here too win7 + strawberry perl

      perl -MConfig -MWin32::Console -E "say $Config{version}; say $Win32::C +onsole::VERSION" 5.14.2 0.10

      thanks

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

        This was just a quick hack thrown together to show what might be done with Win32::Console.

        After I got to the point at which I captured $rect, I dd-ed it (Data::Dump) and found that a string that appeared as, e.g., 'perl...' in the console was dumped as  "p\0\a\0e\0\a\0r\0\a\0l\0\a\0..." I used the
            $rect =~ s{ \0\a\0 } ''xmsg;
        substitution to convert the string back to 'perl...'. Why the extra "\0\a\0" groups were present with each character I don't know; I assume some character set/encoding effect. I didn't investigate further, but just zapped them. I would suggest you do a raw dump of whatever you first get back from the
            my $rect = $con_current->ReadRect($left, $top, $right, $bottom);
        call and adjust as necessary for your system; I don't know what the appropriate  s/// will be for you.

        What you get back from the  ReadRect() call is apparently a single long line without newlines. You then may have to break this string up into lines (possibly triming trailing whitespace) in order to have something useful, but again, I didn't bother with this step. I did find a bunch of blanks may be present at the end of the string, which I got rid of with the
            $rect =~ s{ [ ]+ \z } ''xms;
        substitution. Purely for cosmetic purposes, a further substitution of
            $rect =~ s{ .{$width} \z } ''xms;
        removes the last line with the
            c:\@Work\Perl\monks\gpmathis>capsess
        invocation before printing the  $rect string.

        ... i get the whole text in vertical sense ie only in the first column of the console.

        By this I assume you mean that 'perl...' appears as

        p e r l . . .
        in your console window. I have no idea why this is, but can only suggest that you dump the raw  $rect string returned by the  ReadRect() call and go on from there, hacking away until you get something that looks ok. Good luck.


        Give a man a fish:  <%-{-{-{-<

Re: Saving a Perl session to a file
by marinersk (Priest) on Apr 14, 2017 at 02:56 UTC

    I presume you're trying to use the pipe/redirected output technique, a la foo > t.t 2>&1.

    Windows doesn't work that way on the standard pipe interface; console response is typed not to STDOUTor STDERR, but rather via old-fashioned console output.

    If you want the user's response echoed to the log file, you're going to have to print the answer with a newline yourself, and it will look odd when not so redirected.

Re: Saving a Perl session to a file
by Marshall (Canon) on Apr 14, 2017 at 18:07 UTC
    I occasionally need to capture a Windows cmd window session like the OP wants to do. I don't do it often enough to have worried about creating a special program to do it. I will explain how to manually do this with the normal Windows facilities. Please forgive me if I am being too basic but, I run across folks all the time who do not know how to do this. If the OP doesn't need to do this often, this may be all that is needed?

    Open the command window. Go to the title bar and right click. This brings up a menu. Select Properties. Under Options, select QuickEditMode and InsertMode. Under Command History, run Buffer Size to 999. Hit "OK". When the confirmation screen shows up, Select "Save properties for future windows with same title" and hit OK. As long as you start the command window in the same way as you did this time, you won't have to do these configuration steps again.

    To use this: Hold down the left mouse button to paint the text that you want. The selected area will be highlighted as a rectangle on the screen. The screen will scroll if you need more lines than are on the current screen. Let go of the left mouse button. Tap the right mouse button. This copies the highlighted cmd window rectangle to the clipboard and the highlighting disappears. Now you can use CTL-V or other method to paste the clip board into a text editor.

    Note that with the command window, the normal CTL-C, CTL-V doesn't work (all key presses go to the command line). You have to use the mouse. A right click will copy the clipboard to the current command line. If you accidentally tap the right click twice in the previous paragraph, you will see that highlighted text was copied to clip board and then the 2nd click inserts it again on the command line usually with confusing and bogus results. Clip board is still ok. I mention this because everybody will inevitably make this little mistake.

    Oh, the CLS command clears the screen. If I know that I am going to make a copy of the next commands/responses, I issue a CLS to clear the screen to make finding the desired text easier.

    My memory may not be completely right, but my recollection of the Unix script program is that it captures the keystrokes typed, not what was displayed. So this causes problems if say you backspace to change a letter, that backspace will wind up being captured. If a password is echoed as "****", the actual password typed would be captured which is usually not what is desired. I mention this as something to think about when developing some screen capture program.

Re: Saving a Perl session to a file
by gpmathis (Initiate) on Apr 17, 2017 at 12:50 UTC
    Thanks for the many suggestions. I think what is working best for me is using the IO:Tee module. All screen output is also captured in the log file. And as one poster suggested, I just need to add an explicit print to reflect the user input, so it also captured. Here's a simple example:
    use IO::Tee; use IO::File; my $tee = new IO::Tee(\*STDOUT, new IO::File(">myLogfile.log")); select $tee; print "\nHow old are you: "; my $age = <STDIN>; print "\nYou entered $age\n"; my $year = 2017 - $age; print "You were born in $year\n"