Perl system() EXE Permissions?
سؤال
I'm kinda new to running Perl on windows, and I'm having some problems with the system command while trying to run avrdude.exe
to upload a HEX file to a Atmel Microcontroller. These are the Perl commands I am using to execute the command:
$AVR_CMD = "\"".$AVR_DUDE."\"" . " -C" . "\"".$AVR_DUDE_CONF."\"";
$AVR_CMD .= " -v -v -v -v -patmega2560 -cstk500v2";
$AVR_CMD .= " -P\\\\.\\".$PORT;
$AVR_CMD .= " -b115200 -D -Uflash:w:". "\"".$HEX_FILE."\"". ":i";
system($AVR_CMD);
Now, I am printing the final command to ensure that it is OK, and it seems to be. However, there seems to be some sort of permissions problem in the actual execution. When I copy and paste the printed command into the windows terminal, it results in this:
avrdude.exe: Version 5.11, compiled on Sep 2 2011 at 19:38:36
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch
System wide configuration file is BLOCKED FOR SO
Using Port : \\.\COM4
Using Programmer : stk500v2
Overriding Baud Rate : 115200
avrdude.exe: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
Which is evidently avrdude being run with the correct parameters. However, when I run this command using system()
, I receive this output:
avrdude.exe: Version 5.11, compiled on Sep 2 2011 at 19:38:36
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch
System wide configuration file is BLOCKED FOR SO
Using Port : \\.\COM4
Using Programmer : stk500v2
Overriding Baud Rate : 115200
avrdude.exe: ser_open(): can't open device "\\.\COM4": Access is denied.
avrdude.exe done. Thank you.
This leads me to believe that there is some sort of permissions difference between running a command in CMD and running it through system()
. If anyone could offer some insight on this or give me any tips to remedy this problem it would be greatly appreciated. Thanks beforehand.
EDIT: I have written a Perl script that calls avrdude.org after sending a hard reset to the Atmel (based on some code in this thread):
#!/usr/bin/perl -w
use Win32::SerialPort qw( :STAT 0.19 );
use FindBin qw($Bin);
#Do port reset
foreach (@ARGV)
{
if ($_ =~ /-P\\\\\.\\(.*)/)
{
print "Found -P argument - ";
print ("Resetting DTR on " . $1 . "\n");
$P1 = new Win32::SerialPort ($1);
$P1->pulse_dtr_on(1000);
last;
}
}
select(undef, undef, undef, 0.1);
print ("Executing avrdude\n");
system($Bin . "/avrdude.org " . join(" ", @ARGV));
However, this still has the same problem. If the Perl system()
call has the same permissions as running through the command line, then why can I execute the command in the command line, but COM4 access is restricted when I call the same EXE from Perl? :S
المحلول
system
can take either a string argument, like you did, or a list of arguments. In the latter (recommended) case, the shell handles the quoting for you. So, just make a list of the arguments and pass it. Something like this:
my @args = ($AVR_DUDE, " -C", $AVR_DUDE_CONF,
qw(-v -v -v -v -patmega2560 -cstk500v2), "-P\\.\.$PORT",
qw(-b115200 -D -Uflash:w:), $HEX_FILE, ":i");
system(@args);
Note that you do not need to put variables outside double quotes. And you can use other quoting methods to avoid having to escape quotes. E.g.:
"\""
Can be written in any of these forms:
'"'
qw(")
q(")
qq(")
q#"# # etc
See perldoc perlop for more information.
نصائح أخرى
I suspect that your issue may be in quoting the arguments of the command-line.
I tried to simulate your environnement as you did not show the content of all your variables:
use strict;
use warnings;
my $AVR_DUDE = 'avrdude.exe';
my $AVR_DUDE_CONF = 'my-conf';
my $PORT = 'COM4';
my $HEX_FILE = 'file.hex';
my $AVR_CMD;
$AVR_CMD = "\"".$AVR_DUDE."\"" . " -C" . "\"".$AVR_DUDE_CONF."\"";
$AVR_CMD .= " -v -v -v -v -patmega2560 -cstk500v2";
$AVR_CMD .= " -P\\\\.\\".$PORT;
$AVR_CMD .= " -b115200 -D -Uflash:w:". "\"".$HEX_FILE."\"". ":i";
print "$AVR_CMD\n";
Here is the output:
"avrdude.exe" -C"my-conf" -v -v -v -v -patmega2560 -cstk500v2 -P\\.\COM4 -b115200 -D -Uflash:w:"file.hex":i
Does that command work when you paste it in Cmd?
If not you'll have to fix the quoting. I suspect that -C"my-conf"
may be wrong. Try -C "my-conf"
or "-Cmy-conf"
.