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

Hi. Using this code:

system("cmd /c zip.exe -FF \"$mainfilepath\" --out \"$ziprepairedwordfilepath\"" or die "Could not start repair the zip structure of the docx file: $!");

I'm trying to update a corrupt Word docx file text extractor, by pretreating the files with zip's -FF zip repair command. It works well except when the zip corruption of the docx files start reminding zip of split archives, then it asks if it is a single archive or not with a "y" for yes satisfying it.

So can someone help with discussion or what Perl I should use to automatically respond with "y" and {Enter} if asked?

Replies are listed 'Best First'.
Re: How to Automate Response to Executable's Prompt?
by bulk88 (Priest) on Jun 11, 2012 at 04:50 UTC
    Find a command line flag avoids having to type into the process. That "or die" you placed is unreachable code I think. It has to be outside of the system. 0 is success for command line programs usually. If true, its an exit code, and its an error exit code. On some OSes the exit code needs to be converted to be readable to typical C lib exit codes.

    It is much more complicated to type into a process. Really really try and find a way around , look up what "-q" does and try it. If you must type into a command line program, you need IPC::Open3.

      The problem with -q is zip -FF just blows on through and doesn't repair my sample file with the pseudo split archive structure. So I can't use quiet mode without sacrificing what I'm trying to do.

      OK so here is my IPC::Open3 statements so far:

      use IPC::Open3; my ($pid,$zipin, $zipout, $ziperr); $pid = open3 ($zipin, $zipout, $ziperr, system("cmd /c zip.exe -FF \"$ +mainfilepath\" --out \"$ziprepairedwordfilepath\"")); wait; $zipin = print "y\r\n";

      Any suggestion on how to construct wait or waitpid phrases? Right now whatever I do with wait or waitpid, printing 'y' into input, occurs after I enter 'y' by hand. $zipin never writes to the prompt.

      Update

      I'm looking of zip's C++ code in Visual Studio to see if I can compile my own version that always accepts that the archive is one disk.

        $pid = open3 ($zipin, $zipout, $ziperr, system("cmd /c zip.exe -FF \"$ +mainfilepath\" --out \"$ziprepairedwordfilepath\""));
        Thats broken. system read that. And read IPC::Open3. Your calling open3 wrong.
        $zipin = print "y\r\n";
        Thats broken. print read that. Perhaps another monk can comment if the wait() is correct.

        Update: As I reported in another part of this thread, I was able to get zip to compile without asking if my corrupt docx files were single archives or not.

        Also note -q and any other option does not work with -F or -FF. The only thing that works is --out probably also -O or --output-file. One of those three are a requirement whenever using -F or -FF.

Re: How to Automate Response to Executable's Prompt?
by dasgar (Priest) on Jun 11, 2012 at 05:56 UTC

    Based on the fact you mention you're working on Word files and you're calling zip.exe, I'm going to assume that you're on Windows. If so, here's one crazy idea that I'm not will work or not.

    Modify the call to run zip.exe to use the DOS command "start", which will launch the command in a new DOS command prompt window. With the zip.exe running in a new window, you can probably use Win32::GuiTest to interact with that command prompt window.

    That's probably a crazy, complicated idea, but it just might work. If you do decide to try this and are able to get it work, I'd like to know about. However, I suspect that bulk88's suggestion of using IPC::Open3 would probably be easier to implement.

Re: How to Automate Response to Executable's Prompt?
by DrHyde (Prior) on Jun 11, 2012 at 10:44 UTC
    Does this work on your platform?
    system("echo|cmd ...")
    That should put a newline on the program's standard input. If it doesn't work, then you want to use Expect.

      Tried it. Some of the sample corrupt docx work OK with your echo suggestion, but not the ones that usually prompt for answer about a split. Those are going into a race condition with the new echo command repeating ad infinitum:

      Could not find or open I:/socrtwo/Documents/Word Processor/docx/repairable/Ray_of_Hope_Chri +s_edits.dz01 Hit c (change path to where this split file is) s (skip this split) q (abort archive - quit) e (end this archive - no more splits) z (look for .zip split - the last split) or ENTER (try reading this split again):

      Will try the other suggestions in a minute.

      Expect or Expect::Simple look like they would work well. Unfortunately they require IO::Tty and apparently that won't install on Windows :-(. I need to work with Windows because I want to compile with pp to an exe...
        Unfortunately they require IO::Tty and apparently that won't install on Windows :-(.

        Hmmm....partially true. I'm not advocating that you go this route, but if you installed cygwin, in the cygwin environment with it's Perl it is possible to install the Expect modules. However, I'm not entirely sure that you could use pp to package your script into an executable that can be run on a Windows system that does not have the cygwin environment installed.

        Also, I want to point out one other thing to keep in mind before experimenting with cygwin. Supposedly it has an uninstaller. However, it's been my experience that if you want to uninstall cygwin, the only way to cleanly and completely uninstall it is to reinstall the Windows OS. Every time that I have ever tried to uninstall it, it has never completely uninstalled and some pieces of it are still hanging around. Perhaps they have improved the uninstall process over the past several years since I tried to go through the uninstall process.

Re: How to Automate Response to Executable's Prompt?
by BrowserUk (Patriarch) on Jun 11, 2012 at 19:14 UTC

    What version of zip.exe are you using?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

    The start of some sanity?

      Now I'm using 3.0. However your question gave me an idea. I decided instead of using a precompiled zip binary, I'd go in and make a custom compiling which didn't ask the question but assumed one disk archive state for all the corrupt docx/zip files I threw at it and it worked!

      Thanks for everybody's help. Sorry we couldn't find a Perl solution.