Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

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

by syphilis (Archbishop)
on Jul 07, 2007 at 09:19 UTC ( [id://625400]=note: print w/replies, xml ) Need Help??


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

Hi pjf,
That's a good question, and I'll be interested to see what the Win32 experts can come up with.

As regards the suppression of the error message, one could just redirect stderr to the null device (which you do with 2>nul on Windows) ... but you probably knew about that, anyway.

Other than that, all I can think of is to use Win32::Process instead of system(). If the "system" call launched by Win32::Process::Create() fails (in which case it returns 0) you can access good diagnostics via Win32::FormatMessage((Win32::GetLastError()). And if it succeeds, then you can get the exitcode of the process that was launched with $ProcessObj->GetExitCode($exitcode).

Cheers,
Rob

Replies are listed 'Best First'.
Re^2: $? set to strange values on failure under Win32
by garu (Scribe) on Jul 09, 2007 at 06:09 UTC

    Well, I'm no win32 expert, but I might as well give my $0,02c to the issue, hoping it will improve your research ;-)

    First of all, you assumed right as the ('...' is not recognised as an internal or external command) message IS indeed from the Windows shell (I can tell as my Windows is in portuguese and this is the only portuguese message I get when running the example files you guys provided), but you already knew that as 2>NUL would probably not have worked otherwise, I guess ;-).

    Now, from a programmer's point of view, I'm sure you know that return values are only set for convention purposes, and you can create a program returning whatever you want upon success or failure. As BrowserUk mentioned, MS-Windows has its own method of error handling. However, apart from some special WINAPI functions like GetLastError, it's not as foolproof as you'd expect. In fact, Microsoft's very own official Command Shell Overview states that:

    "If a command completes an operation successfully, it returns an exit code of zero (0) or no exit code."

    And I guess people should just comply to this behavior if they want things to work as expected.

    I tested the implications of this via the && shell command (that, again acording to Microsoft, runs the command following "&&" only if the command preceding the symbol is successful) and, not surprinsingly, here's what I got:

    C:\>perl -e "exit 0" && echo "ok" "ok" C:\>perl -e "exit 1" && echo "ok" C:\>perl -e "exit -1" && echo "ok" C:\>

    As you can see, there was no error whatsoever, and still the cmd.exe shell only thought of it as ok when it returned 0. In fact, the %ERRORLEVEL% system environment variable is supposed to hold the error code of the most recently used command, a non zero value usually indicating an error (from MS's description in the above link), but it simply holds the value returned by the program (in my example it was 0, 1 and -1 respectively).

    This is supposed to be well-known by every Windows programmer (is it?), and WinError.h has a comprehensive list of 16000 System Error Codes with their respective descriptions. Signal Handling is in itself another problem: although Microsoft's definition states that all signal-terminated programs should have the return value of 3 (oddly enough, not the correct WinError.h definition - but maybe I messed up on their file versions, or maybe there's a different message table for this, or maybe I just got it all plain wrong), perl returns the actual signal value. For instance:

    C:\> perl -e "while (1) { sleep 1; }" (now I pressed ^C) Terminating on signal SIGINT(2) C:\> echo %ERRORLEVEL% 2

    By the way, this is what I got when I ran BrowserUk's code on my WinXP/ActivePerl 5.8.8 (build 820):

    C:\>perl pjf-win32.pl 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[]

    Just to be sure it was not a "Windows perl implementation issue", I tested it on Vanilla-Perl 5.8.8, getting the exact same messages.

    Although I think you'll hit the same deadend in Win32 and Win32::Process, I hope you succeed and let us know how you did it!

    Hope I understood your problem correctly, and hope it helped somehow :-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://625400]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-23 22:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found