in reply to Re: $? set to strange values on failure under Win32
in thread $? set to strange values on failure under Win32

If $^E is empty, the command ran successfully

Yes, but the command can run successfully and, yet, there will still be an error message in $^E (which is merely the last error, n'est-ce pas ?). When I run the script you provided I get the following output:
C:\_32\pscrpt>perl try.pl Successful command returning 1 ![Bad file descriptor] ?[256 : 1] E[The specified image file did not c +ontain a r esource section] Nonexistant command, attempted direct but fallback to via cmd 'c:/doesNotExists.exe' is not recognized as an internal or external co +mmand, operable program or batch file. ![No such file or directory] ?[256 : 1] E[There are no more files] Nonexistant via cmd because of the presence of shell chars sending std +err >null ![No such file or directory] ?[256 : 1] E[There are no more files]
Admittedly 1) and 3) are different, but I wouldn't like to have to work out which had succeeded and which had failed based solely upon the ouptut :-)

I'm at a loss for the moment to understand why the expected error message never appears in $^E for me. (I'm on Windows Vista - but I don't think that's an issue. I'll switch to XP and see what happens.)

Cheers,
Rob
Update:On Windows 2000 I find that BrowserUk's script runs as he has reported. However, if one inserts a system'c:/doesNotExist.exe'; immediately below the use strict; in BrowserUk's script then $^E is no longer useful for determining whether the other three ensuing commands ran successfully or not. (My XP laptop has shit itself again, so I had to resort to Windows 2000).

Replies are listed 'Best First'.
Re^3: $? set to strange values on failure under Win32
by BrowserUk (Patriarch) on Jul 07, 2007 at 11:21 UTC

    What results do you get on vista from this version?

    #! perl -slw use strict; undef $^E; undef $!; print 'Successful command returning 1'; system 'c:/perl/bin/perl.exe -e"sleep 5; exit 1"'; print "![$!] ?[@{[$?, ':', $?>>8]}] E[$^E]"; undef $^E; undef $!; print "\nNonexistent command, attempted direct but fallback to via cmd +"; system 'c:/doesNotExists.exe'; print "![$!] ?[@{[$?, ':', $?>>8]}] E[$^E]"; undef $^E; undef $!; print "\nNonexistent via cmd because 'shell chars'; sending stderr >nu +ll"; system 'c:/doesNotExists.exe 2>null'; print "![$!] ?[@{[$?, ':', $?>>8]}] E[$^E]"; __END__ C:\test>junk Use of uninitialized value in undef operator at C:\test\junk.pl line 4 +. Successful command returning 1 ![] ?[256 : 1] E[] Use of uninitialized value in undef operator at C:\test\junk.pl line 1 +0. Nonexistent command, attempted direct but fallback to via cmd 'c:/doesNotExists.exe' is not recognized as an internal or external co +mmand, operable program or batch file. ![No such file or directory] ?[256 : 1] E[The system cannot find the f +ile specified] Use of uninitialized value in undef operator at C:\test\junk.pl line 1 +6. Nonexistent via cmd because 'shell chars'; sending stderr >null ![] ?[256 : 1] E[The system cannot find the file specified]

    Aside: That Use of uninitialized value in undef operator ... wins the

    BrowserUk Award with Special Commendation" in the category of "Most Useless Warning of the Week Month Year Ever".

    And that's in a highly contested category. :)


    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.
      What results do you get on vista from this version?

      It makes no difference on Vista (apart from occurrences of Use of uninitialized value in undef operator ... :-)

      However, on Windows 2000 (and probably XP, too) it has the desired effect. As long as the op does an undef($^E); before running the system command, I don't envisage any problem with your proposed solution on XP and Windows 2000.

      Here's a copy'n'paste of what I get on Vista:
      C:\_32\pscrpt>perl try.pl Use of uninitialized value in undef operator at try.pl line 4. Successful command returning 1 ![] ?[256 : 1] E[The specified image file did not contain a resource s +ection] Use of uninitialized value in undef operator at try.pl line 10. Nonexistent command, attempted direct but fallback to via cmd 'c:/doesNotExists.exe' is not recognized as an internal or external co +mmand, operable program or batch file. ![No such file or directory] ?[256 : 1] E[There are no more files] Use of uninitialized value in undef operator at try.pl line 16. Nonexistent via cmd because 'shell chars'; sending stderr >null ![] ?[256 : 1] E[There are no more files]
      I tried a couple of different builds of perl-5.8.8 on Vista (being sure to ammend the path to perl appropriately each time) and the output doesn't change.

      Anyway, pjf did specify "XP".

      Cheers,
      Rob

        BrowserUk/Rob, your responses are gold. Your answers are exactly the sort of information I was after.

        However it appears that $^E isn't yet my saviour. Under my Windows XP system I get the following results (uninitalized warnings trimmed):

        #! perl -slw use strict; undef $^E; undef $!; print 'Successful command returning 1'; system 'c:/perl/bin/perl.exe -e"sleep 5; exit 1"'; print "![$!] ?[@{[$?, ':', $?>>8]}] E[$^E]"; undef $^E; undef $!; print "\nNonexistent command, attempted direct but fallback to via cmd +"; system 'c:/doesNotExists.exe'; print "![$!] ?[@{[$?, ':', $?>>8]}] E[$^E]"; undef $^E; undef $!; print "\nNonexistent via cmd because 'shell chars'; sending stderr >nu +ll"; system 'c:/doesNotExists.exe 2>null'; print "![$!] ?[@{[$?, ':', $?>>8]}] E[$^E]"; __END__ Successful command returning 1 ![] ?[256 : 1] E[] Nonexistent command, attempted direct but fallback to via cmd 'c:/doesNotExists.exe' is not recognized as an internal or external co +mmand, operable program or batch file. ![No such file or directory] ?[256 : 1] E[] Nonexistent via cmd because 'shell chars'; sending stderr >null ![] ?[256 : 1] E[]

        It appears that redirecting stderr makes an unsuccessful command appear to be a successful command. When an error does occur, it's found inside $! and not $^E, which seems to never be set. Oh my!

        Unfortunately this leaves me with the same tangle as Perl itself has in emulating system() under Windows. Ideally I want to preserve the following behaviours:

        1. Single argument call always goes via the shell
        2. Multi argument call never goes via the shell
        3. It's possible to tell when a command didn't start (ostensibly via $? being set to -1)

        Using the shell means I don't have a reliable way of determining failure to start a command. Not using the shell means I may have to potentially go searching through $ENV{PATH} by hand.

        I guess this is an excellent opportunity for me to go searching for that discussion by tye, and potentially go looking through Perl's source for system() under Windows. I suspect my final result will make heavy use of Win32:: modules to provide the required behaviour.

        Many thanks again!

        Update: Working with Win32::Process is showing great promise.