http://www.perlmonks.org?node_id=177124

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

Thanks to everyone who has provided direction to me as I embark on using Win32::Process. Migrating from system() to Win32::Process has been anything but easy. However, I have overcome one major obsticle, to encounter another.

When I launch a new process, I want to be able to take the contents of the ourput and direct it to my $dump file. However, i cannot figure out how to redirect this output. I do not want to redirect all cmd output, just what the command 'identify' generates.

I have seen many documents throughout the web, yet none have provided me the right way to go. Even the man ages left me scratching my head. Once again, I have included the code in case you may have questions on my code.


thanks again.
simon.
############################################################# # This script checks the validity of image files using # # Image Magick's Identify command. This script works with # # various file formats. Several variables can be changed to # # altering logging and analysis. # # # # Simon D. Yates 30may02. # # Simon D. Yates Version 2.00.0168 18jun02. # ############################################################# # Allow this for emailing on errors. Will also require the email metho +d # Email me at sdyates2001@yahoo.com for the method. # use LWP::UserAgent use File::Find; use Win32::Process; #>---------------[ Customisable variables ]----------------- my $SummaryHTML = ">c:\\sdy\\summary.html"; # Location of Summary.html. Report summary in html format. my $SummaryCSV = ">c:\\sdy\\summary.csv"; # Location of Summary.csv. Report summary in csv format. my $SummaryCSVread = "<c:\\sdy\\summary.csv"; # Location of dump.txt. Contains granular data on each image tested. my $dump = "c:\\sdy\\dump.txt"; # Location of error.txt. Contains a list of potentially corrupt images +. my $error = ">>c:\\sdy\\error.txt"; # Specify "yes" to allow good images to be copied to $CopyDestination my $CopyGoodImages = "yes"; # by-passes prompting sections when set to other than no my $AutoScript = "yes"; # Specify the root directory where the images will be analysed and cop +ied from my $CopySource = "j:\\ClientSupportFiles\\workbook"; # Specify the directory where the good images will be copied to my $CopyDestination= "c:\\sdy"; #>----------------------[ variables ]------------------------ my @Structure=('\#\#','Format','Geometry','Class','Type','Depth', 'Colors','Filesize','Compression','Tainted'); #>---------------------[ Main logic ]------------------------ # Generates time stamp for log files Date(); # prompts for Source directory. RetrieveValues(); # Analyse each image and dump raw data and log errors CheckImageArchieve(); # Create summary file of images processed GrepImageDetails(); print OUTPUT "\n"; # Creates HTML file from CSV file PrintHTML(); #>----------------[ Subroutine Section ] -------------------- sub RetrieveValues { if ($AutoScript eq "no") { print "\n\nSpecify the Directory path to image folder:\n"; $directory = (<STDIN>); chomp $directory; } } sub CheckImageArchieve { my $a = 0; if ($AutoScript = "yes") { $directory=$CopySource } opendir(DIR, $directory) or die "Cannot open directory $directory" +; find (\&RetrieveAll, $directory); system ("cls"); while ($DIR[$a]) { open (STDERR, "$error") or die "$!"; # verbose option is critical for creating summary file $file="$DIR[$a]"; if (-d $file) { system("echo ##: $DIR[$a](SUB DIRECTORY) >> $dump"); print "DIR: $file" . "\n" } elsif (-f $file) { system("echo ##: $DIR[$a] >> $dump"); print "$DIR[$a]\n"; $DIR[$a] =~ s/\\/\\\\/g; Win32::Process::Create($ProcessObj,"J:\\imagemagick\\win2k +\\ImageMagick\\identify.exe","identify -verbose $DIR[$a] >> $dump",0, +NORMAL_PRIORITY_CLASS,"."); $ProcessObj->Wait(INFINITE); $ProcessObj->GetExitCode( $ExitCode ); print "\nExit: $ExitCode\n"; if ($ExitCode ne "1") { print STDERR "##: $DIR[$a] likely corrupt!\n". "--------------------------------------------- +-----\n"; $img="bad"; } else { $img=(); } CopyGoodImage(); } $a=$a+1; close STDERR; } } sub GrepImageDetails { open (INFILE, "<$dump") or die "Cannot open $dump file"; open (OUTPUT, $SummaryCSV) or die "Cannot open Summary CSVfile"; print OUTPUT "\n$Date\n"; print OUTPUT "File,Format,Geometry,Class,Type,Depth,Colors,Filesiz +e,Compression,Tainted"; while (<INFILE>) { $SFS = $_; $z=0; foreach $Structure(@Structure) { if ($SFS =~ m/$Structure[$z]/) { if ($Structure[1] =~ m/Format/) { if ($SFS =~ m/\#\#/) { print OUTPUT "\n"; } } $SFS =~ s/$Structure[$z]: //; $SFS =~ s/ //g; $SFS =~ s/\r//g; chomp $SFS; if ($z ne 9) { print OUTPUT $SFS . ","; } else { print OUTPUT $SFS; } print $SFS . "\n"; } $z=$z+1; } } $z=$z+1; close INFILE; close OUTPUT; } sub Date { ($sec,$min,$hou,$day,$mon,$yer,$wek,$dy,$DST)=localtime(time); my $rlm=$mon+1; my $yer=$yer+1900; if ($rlm == 1) {$rlm = "Jan"} elsif ($rlm == 2) {$rlm = "Feb"} elsif ($rlm == 3) {$rlm = "Mar"} elsif ($rlm == 4) {$rlm = "Apr"} elsif ($rlm == 5) {$rlm = "May"} elsif ($rlm == 6) {$rlm = "Jun"} elsif ($rlm == 7) {$rlm = "Jul"} elsif ($rlm == 8) {$rlm = "Aug"} elsif ($rlm == 9) {$rlm = "Sep"} elsif ($rlm == 10) {$rlm = "Oct"} elsif ($rlm == 11) {$rlm = "Nov"} elsif ($rlm == 12) {$rlm = "Dec"}; $Date="$hou"."h"."$min:$sec $rlm-$day-$yer"; } sub RetrieveAll { $File::Find::dir =~ s/\//\\/g; $_ =~ s/\//\\/g; push (@DIR,$File::Find::dir."\\".$_); } sub SummaryHTML { print OUTPUTHTML "</tr></table></p></BODY></HTML>"; } sub PrintHTML { open (OUTPUTHTML, $SummaryHTML) or die "Cannot open Summary HTML f +ile"; open (SUMMARY, "$SummaryCSVread") or die "Cannot open $dump file"; print OUTPUTHTML "<HTML><HEAD> <META NAME='GENERATOR' Content='Zoom Image Server Library'> <TITLE></TITLE> </HEAD> <TABLE BORDER=0 width=1000 cellpadding=2 align=left bordercolo +r='#FF9933' body bgcolor=steelblue> <TR><TH><font face=arial size=2>File name</TH> <TH><font face=arial size=2>Format</TH> <TH><font face=arial size=2>Pixel size</TH> <TH><font face=arial size=2>Class</TH> <TH><font face=arial size=2>Depth</TH> <TH><font face=arial size=2>Colour Depth</TH> <TH><font face=arial size=2>Colours</TH> <TH><font face=arial size=2>File size</TH> <TH><font face=arial size=2>Compression</TH> <TH><font face=arial size=2>Tainted</TH></TR> <font face='Courier'><TR><TH>"; $directory=~ s/\\/\\\\/g; while (<SUMMARY>) { $line=$_; $line =~ s/,/\<\/td\>\n\<td width='100' height='20' font face= +arial size='1' bordercolor='#FFFFCC' bgcolor='#FFFFCC' align=left\>/g +; # replace with scalar representing the path if ($line =~ m/$directory/) { print OUTPUTHTML "<tr><td width='150' height='20' font fac +e=arial size=1 border='1' bordercolor='#FFFFCC' bgcolor='#FFFFCC' ali +gn='left'>$line</td></tr>"; print OUTPUTHTML "\n"; } } close SUMMARY; close OUTPUTHTML; } sub CopyGoodImage { if ($img eq "bad") { print "$file is potentially damaged.\nFile not coppied!\n\n"; $img=(); } else { print "$file is fine\n"; if ($CopyGoodImages eq "no") { print "File copy is turned off\n\n"; $img=(); } else { print "Copying $file ...\n"; system ("copy $file $CopyDestination\n"); } print "\n"; $img=(); } }

Edit kudra, 2002-06-25 Added readmore

Replies are listed 'Best First'.
Re: Win32::Process redirect CMD output to text file
by flounder99 (Friar) on Jun 25, 2002 at 16:48 UTC
    I think Win32::Process::Create creates a new process directly from the program you send it. It does not start a shell and then have the shell start the process. Redirecting is a function of the shell. You may have to start "cmd" or "command" (depending on your shell) and have it start identify.exe in your Win32::Process::Create call.

    --

    flounder

      Eitherway, I should be able to redirect the contents of the command from the screen to a file on disk. If I can do this using system, I am sure I can do it with Win32::Process, just cannot figure out how to do it. I cannot believe that Win32::Process would be lacking in that area. I am more convinces in my own ignorance that Win32's ignorance.

        Here, look at this
        use Win32::Process; Win32::Process::Create($ProcessObj, 'c:\winnt\system32\cmd.exe', "/c echo foo>foo.txt", 0, NORMAL_PRIORITY_CLASS,".")||warn "could not create process";
        instead of echo foo put in the program you want to run. Win32::Process is doing what you ask of it - it is creating a process running "identify.exe". "indentify.exe" does not know how to redirect. You have to run "cmd.exe" and have it start "identify.exe" and redirect the output to a file. system transparently starts a shell (cmd.exe) and hands it the parameters, the first of which is the program it should run. Most people from a windows background don't understand that a command prompt is actually a program called "cmd.exe" (or "command.com" on dos/win9x)

        Update:
        Note: the name of your shell is probably available in $ENV{COMSPEC}

        --

        flounder