Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Hi all,

I noticed a strange behaviour of the system() function on windows, and I would like to understand how _exactly_ is system() implemented on Win OS'es...

According to perl's documentation, system() can be used in two ways: either passing it a string as a _single_ argument, which contains the external program to execute plus all needed arguments. E.g.:

system("my_program arg1 arg2 arg3");

Or you can pass it an array, of which the first element is then taken as the program name to execute, and the remaining elements are passed as separate arguments to the program.

system("my_program", "arg1", "arg2", "arg3");

According to docs, the difference between the first usage and the second usage is that when passing a single string, perl first checks if the string contains any shell metacharacters, and if it does - system() calls the shell and passes it the whole string as command. In the second usage, system() never calls any OS shell, but directly executes the program and passes the array elements as separate arguments, EXACTLY as they are. Regardless if the array elements contain spaces or special characters or anything, each of them is passed to the external program as one and exactly one argument.

Now... This is true, and works perfectly well on Unix. But not on Windows. As an example, let's use a simple executable, that (I think) is available on every windows machine: msg.exe. It can take some options and arguments, but basically it presents a message box with some text to the user. In the simplest form, you can manually execute this on the command line:

msg username "some text"

where "username" is your windows ser name, and it will display a message box with the text "some text". (Btw. the command works even without the double-quotes around "some text".) But now to the problem with perl's system() function. My goal is to execute an external program, and be able to pass it my arguments EXACTLY as they are. no interpretation whatsoever. Since I know that the first usage of system() - i.e. giving it the full command with arguments as one string - might involve the local OS shell, I decide to not use it. But use the array form instead. So first check this sample code:

my $txt = 'sample text with some / special /w characters > xyz'; system('msg', 'username', $txt);

This works OK. The whole string in $txt is diplayed in the message box, and it looks like system() is working correctly. But this code:

my $txt = '/w sample text with some / special /w characters > xyz'; system('msg', 'username', $txt);

does not work anymore! The only difference is the /w at the beginning of the message text. But it shows that something strange is happening behind the scenes, when system() runs. /w is an option for msg.exe which tells it to wait until user clicks OK. And in fact when I execute the perl script, I can see two things: First, the message box does not display the whole text that is in $txt, it only starts with the word "sample". And second: the command line prompt does not return immediately, it only comes back when I click on OK. (This is because the script waits for system() to complete, system() waits for msg.exe to complete, and msg.exe waits for my click.

Sooo... Reading perl docs, I would expect that system() executes my program (msg.exe), and passes it the "username" as first argument, and the complete $txt content (whatever characters it might contain!) as a second argument. Instead, it looks like system() still builds one long command first, using the array elements provided, and then somehow executes all of it: (although I do not see any additional shell i.e. cmd.exe running in the task manager)

msg username /w sample text with some / special /w characters > xyz

This is in my opinion incorrect! And the big question is: What does system() actually do behind the scenes, because what I ultimately need, is the possibility to pass _arbitrary_ arguments to my external program, even with special characters etc.

BTW. I tried ActivePerl and Strawberry perl, and they both have the same issue.

If there are any monks out there, who know how this stuff is exactly implemented on Windows, I would greatly appreciate an answer.


In reply to system() implementation on Windows (again) by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-25 10:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found