Start perl script with Win32::Process::Create - perl

I would like to translate all of the system commands in my script to Win::32::Process::Create commands. CPAN tells me the syntax:
Win32::Process::Create($obj,$appname,$cmdline,$iflags,$cflags,$curdir)
So, I tried to apply it:
Win32::Process::Create( $Win32processObj,
"C:\\Perl64\\bin\\perl.exe",
"'C:\\Users\\script.pl','$arg'",
0,
NORMAL_PRIORITY_CLASS,
"." ) || die "Failed to create process.\n";
When I run this, I don't get an error, but I don't start a new process either...
When I use GetProcessID(), I get a pid, but it doesn't correspond to anything in the tasklist... (I'm assuming the created process ends before I can see it displayed in the tasklist).

According to your comment, Windows says it created the process. Accoding to your question, you even have its process id of the process you claim never got created. I'm gonna go out on a limb and say you are mistaken.
You should now check what code the process ended with. perl -E'say $!=THECODE;' might give you a hint. But chances are it's because you tell Perl to execute a file named 'C:\Users\script.pl' (as opposed to C:\Users\script.pl).

Related

How to do 'Wait and Answer to System' with Perl

I am writing a Perl that automatically interacts with another script.
The script needs double confirm for some critical operations.
Executing the script without Perl is something like the following:
$ ./TheScript
TheScript Starting.......
Following step might be harmful to your system.
Are You Sure (Y/N)?
$ Y
TheScript finished!
Now I want a Perl script doing that for me.
I am sure that (Y/N) confirmation will exist within 10 sec. So I've tried:
system('./TheScript');
sleep 10;
system('Y');
This failed because it stuck in system('./TheScript') and did not
go to the rest of the script including reply 'Y'.
Backstick ` is almost the same as system except it captures the STDOUT.
exec() is more impossible because it forks TheScript and is not able to do anything on it again.
Did I make any mistakes doing the analysis? Or are there any functions doing what I want?
You misunderstand the system function. It waits for the program to exit before your Perl program continues.
To drive an interactive program from Perl, you want the Expect module (or perhaps Expect::Simple). However, for a very simple case like you're suggesting, IPC::Open2 may suffice, and it's a core module.
As per your written Perl script, you are facing issue when double confirmation occurred by the system. So for that I can suggest, you can write the script in such way that ,
first it checks first confirmation OK fine
if next again it asks confirmation , your script must check second confirmation as well
for this ,
my $conf= "Are You Sure (Y/N)?"; my $length = $conf; if ($length > 0) { sleep 0; system('Y'); } else { system('N'); }
I hope , this script will be fine for you.

ZSH Magic for certain exit-status situations

Hey I thought about writing a function that prompts me in certain situations (perl had a bad exit status and the warning it prints starts with "Could not find * in #INC) with maybe re-running the command.
Do you think this is feasable?
I have found that TRAPZERR function. but i don't even get the name of the last command in there, only the last argument, so one concrete point would be: how can I get the command-name out of it? !!:0 doesn't work.
Next thing is: i think i might have to do some tricks with preexec to catch the first line of the stderr (if that doesn't work that's not a big problem, but it would be interesting anyway), I thought about appending an 2> to a pipe or something but I'm not sure how to get that pipe constructed in the first place. But as stated above, this is a minor issue.
But really, if you think: No this task is impossible! Please tell me so (although I would be interested why).
From the one answer i got until now I think i can narrow down the problem a little:
Is it possible to wrap a MULTIOS redirection around a perl script? ( I thought about some special kind of exec, but came up with none that worked)
Here's a start.
preexec() {
lastcommand=$1
exec 3>&1 4>&2
exec 2> >(tee /tmp/output 1>&4)
}
precmd() {
read line </tmp/output
case "$line" in
"Can't locate"*)
echo "Perl module missing running $lastcommand"
;;
esac
}
But maybe you want to do something at the language level like How can I hook into Perl's use/require so I can throw an exception?

Can't exec "bin" : Bad file descriptor (Perl)

I'm trying to fix a problem for a day and after many unfructuous searches i'm here !
I'm trying to use the binary convert from the ImageMagick suite on a Perl script to crop an picture.
When i try this simple code :
use Shell qw(convert);
convert("-crop", "50%x50%", $Src, "new_image.png");
On a single file that works perfect.
But when i try to implement it on the project i'm working on (i'm on internship ,fixing features now), the message "Can't exec convert : Bad file descriptor" appears !
I checked the path of $Src, try to remplace by hard code, set PATH, nothing change.
BUT
if i try a simple:
convert(-h);
That Works perfect !
I supposed something in the previous code may be interfering but not sure.
Ps : The project is launched from a php server hosted in local, donno if it change something but if never !
Thanks a lot for reading and thank too for answering !
---EDIT---
Actual code as asked
Use Shell qw(convert);
.
.
.
sub checkSubScreen
{
#Parameters init
my ($this, $Scr0, $Scr1) = #_;
convert("-crop", "50%x50%", $Scr0, "tmp/scr0_crp.png");
convert("-crop", "50%x50%", $Scr1, "tmp/scr1_crp.png");
....
I can't show you the entire code it's really too big but just ask and i'll try to show !
The error message comes from Shell. I don't know what anyone thinks they are gaining by using Shell instead of the more traditional system/qx/pipe open/IPC::Open3 toolkit, and in particular I don't see what you are gaining by using Shell.
Try the more traditional system call
#args = ("50%x50%", $Src, "new_image.png");
system("convert", #args) and warn "convert #args: exit code was $?";
and see if you get a more traditional error message.
Ok finally i decided to use the PerlMagick Api it works, i think my problem was due to the environment and probably very specific.
Thks for answers !

.pm file that's loaded on every invocation of the perl interpreter?

I thought I remember reading somewhere about where perl can be configured to automatically load a certain .pm file on start up.
I know about PERL5OPT, but to my recollection, this was a specific file that would be loaded if it exists.
Is it a compile option that can be set (i.e. via Configure)?
Reading through perldoc perlrun it looks like you are looking for what is talked about in the -f option:
-f
Disable executing $Config{sitelib}/sitecustomize.pl at startup.
Perl can be built so that it by default will try to execute
$Config{sitelib}/sitecustomize.pl at startup (in a BEGIN block). This
is a hook that allows the sysadmin to customize how Perl behaves. It
can for instance be used to add entries to the #INC array to make Perl
find modules in non-standard locations.
Perl actually inserts the following code:
BEGIN {
do { local $!; -f "$Config{sitelib}/sitecustomize.pl"; }
&& do "$Config{sitelib}/sitecustomize.pl";
}
Since it is an actual do (not a require), sitecustomize.pl doesn't
need to return a true value. The code is run in package main , in its
own lexical scope. However, if the script dies, $# will not be set.
The value of $Config{sitelib} is also determined in C code and not
read from Config.pm , which is not loaded.
The code is executed very early. For example, any changes made to #INC
will show up in the output of perl -V. Of course, END blocks will be
likewise executed very late.
To determine at runtime if this capability has been compiled in your
perl, you can check the value of $Config{usesitecustomize} .
I've never done this, but it looks like if you put what you want in $Config{sitelib}/sitecustomize.pl you'll get what you are looking for.
See:
http://perldoc.perl.org/perlrun.html
http://www.nntp.perl.org/group/perl.perl5.porters/2007/10/msg129926.html
I'm confused by what you mean by "on start up". If you mean when a script / CGI / whatever is "started", then just use the module in the script:
use Data::Dumper;
Or do you mean something else?

How can I determine if the script is being executed within a system or qx call in Perl?

In Perl, is it possible to determine if a script is being executed within another script (presumably via system or qx)?
$ cat foo.pl
print "foo";
print "\n" if not $in_qx; # or the like.
I realize this is not applicable if the script was being run via exec.
I know for certain that system runs the process as a fork and I know fork can return a value that is variable depending on whether you are in the parent or the child process. Not certain about qx.
Regardless, I'm not certain how to figure out if I'm in a forked process without actually performing a fork.
All processes are forked from another process (except init). You can sort of tell if the program was run from open, qx//, open2, or open3 by using the isatty function from POSIX, but there is no good way to determine if you are being run by system without looking at the process tree, and even then it can get murky (for instance system "nohup", "./foo.pl" will not have the calling perl process as its parent).
You could check "who's your daddy", using "getppid" (get parent id). Then check if your parent id is a perl script with pgrep or similar.
Do you control the caller? The simplest thing to do would be to pass an argument, e.g. --isforked.