What is the equivalent of ps command in perl? - windows

I am using ps -C <executable name> on Linux, but the same does not work on Windows.
How can I perform the same check in Perl so that it is platform independent?

You might be able to use Win32::Process::List
use 5.12.0;
use warnings;
use Win32::Process::List;
my $P = Win32::Process::List->new();
if($P->IsError == 1) {
die $P->GetErrorText;
}
my %list = $P->GetProcesses();
foreach my $key (keys %list) {
# $list{$key} = process name, $key=PID
say sprintf("%25s %10s", $list{$key}, $key);
}
And process appropriately.

Related

How can Perl see where a Windows shortcut points to?

In Windows, how can I check where a shortcut file points to? In the following simple code, readlink doesn't show anything:
$dir = 's:\\aaaaa\\bbb';
.....
#img = readdir F;
#lnk = grep{/lnk$/} #img;
......
......
foreach (#lnk){
$where = readlink $dir.$_;
$a=$a;
}
According to perlport, readlink is not implemented on Windows. Instead you can use Win32::Shortcut to read shortcut .lnk files:
use strict;
use warnings;
use feature qw(say);
use Win32::Shortcut;
my $link = Win32::Shortcut->new();
$link->Load("test.lnk");
say "Shortcut to: $link->{'Path'} $link->{'Arguments'}";
$link->Close();

Perl module File:Slurp with STDIN piped

I have just tried using the following Perl script to do some text substitution using the File::Slurp module. It works fine on a single file given as an argument at the command line (BASH).
#!/opt/local/bin/perl -w
use File::Slurp qw( edit_file_lines );
foreach my $argnum (0 .. $#ARGV) {
edit_file_lines {
s/foo/bar/g;
print $_
}
$ARGV[$argnum];
}
I would like to alter it to cope also with pipes (i.e. STDIN), so that it can be in the middle of a series of piped operations:
for example:
command blah|....|my-perl-script|sort|uniq|wc....
What is the best way to change the Perl script to allow this, whilst retaining the existing ability to work with single files on the command line?
To have your script work in a pipeline, you could check if STDIN is connected to a tty:
use strict;
use warnings;
use File::Slurp qw( edit_file_lines );
sub my_edit_func { s/foo/bar/g; print $_ }
if ( !(-t STDIN) ) {
while(<>) { my_edit_func }
}
else {
foreach my $argnum (0 .. $#ARGV) {
edit_file_lines { my_edit_func } $ARGV[$argnum];
}
}
See perldoc -X for more information on the -t file test operator.
All you need is the following:
local $^I = '';
while (<>) {
s/foo/bar/g;
print;
}
This is basically the same as perl -i -pe's/foo/bar/', except it doesn't warn when STDIN is used.

Why Windows generate a lot of process for a compiled Perl script?

I've written this script (called SpeedTest.pl) to log internet speed due to resolve a problem with my ISP.
It work well, but just if I use a Perl interpreter (if I double-click on the script). I want to compile it to generate a stand-alone executable to run in a different PC without Perl installed.
Well, I've try with pp and Perl2Exe both, but when I launch the SpeedTest.exe i see a lot of process called "SpeedTest.exe" in task manager. If I don't block all these process, the PC OS will crash (a pop-up say: "the memory can't be written, blah blah blah).
Any ideas?
This is the script:
#!/usr/local/bin/perl
use strict;
use warnings;
use App::SpeedTest;
my($day, $month_temp, $year_temp)=(localtime)[3,4,5];
my $year = $year_temp+1900;
my $month = $month_temp+1;
my $date = "0"."$day"."-"."0"."$month"."-"."$year";
my $filename = "Speed Test - "."$date".".csv";
if (-e $filename) {
goto SPEEDTEST;
} else {
goto CREATEFILE;
}
CREATEFILE:
open(FILE, '>', $filename);
print FILE "Date".";"."Time".";"."Download [Mbit/s]".";"."Upload [Mbit/s]".";"."\n";
close FILE;
goto SPEEDTEST;
SPEEDTEST:
my $download = qx(speedtest -Q -C --no-upload);
my $upload = qx(speedtest -Q -C --no-download);
my #download_chars = split("", $download);
my #upload_chars = split("", $upload);
my $time = "$download_chars[12]"."$download_chars[13]"."$download_chars[14]"."$download_chars[15]"."$download_chars[16]";
my $download_speed = "$download_chars[49]"."$download_chars[50]"."$download_chars[51]"."$download_chars[52]"."$download_chars[53]";
my $upload_speed = "$upload_chars[49]"."$upload_chars[50]"."$upload_chars[51]"."$upload_chars[52]"."$upload_chars[53]";
my $output = "$date".";"."$time".";"."$download_speed".";"."$upload_speed".";";
open(FILE, '>>', $filename);
print FILE $output."\n";
close FILE;
sleep 300;
my($day_check, $month_temp_check, $year_temp_check)=(localtime)[3,4,5];
my $year_check = $year_temp_check+1900;
my $month_check = $month_temp_check+1;
my $date_check = "0"."$day_check"."-"."0"."$month_check"."-"."$year_check";
my $filename_check = "Speed Test - "."$date_check".".csv";
if ($filename = $filename_check) {
goto SPEEDTEST;
} else {
$filename = $filename_check;
goto CREATEFILE;
}
Well, Steffen really answered this by way of a Comment, but here it is as an Answer. Just compile your Perl into an EXE that does NOT have the same name as the one that the Perl script is calling, for example:
speedtest.pl compiled into myspeedtest.exe, which calls speedtest.exe

Can't locate WWW/Mechanize.pm: Using cpanm doesn't work

I know this is a duplicate, but my question was not answered in any other threads. the output of sudo cpanm WWW::Mechanize is to long to put in tread. pastebin: 3BYUtSss
I tried executing a perl script, and I get this error:
Can't locate WWW/Mechanize.pm in #INC (#INC contains: /opt/local/lib/perl5/site_perl/5.16.3/darwin-thread-multi-2level /opt/local/lib/perl5/site_perl/5.16.3 /opt/local/lib/perl5/vendor_perl/5.16.3/darwin-thread-multi-2level /opt/local/lib/perl5/vendor_perl/5.16.3 /opt/local/lib/perl5/5.16.3/darwin-thread-multi-2level /opt/local/lib/perl5/5.16.3 /opt/local/lib/perl5/site_perl /opt/local/lib/perl5/vendor_perl .) at io.pl line 5.
In case you need it, here is my perl script's contents:
#!/usr/bin/env perl
use warnings;
use strict;
use WWW::Mechanize;
my $mech = WWW::Mechanize->new();
my ($get,$host,$title);
while (<>) {
if (m|^GET (\S+) |) {
$get = $1;
} elsif ( m|^Host: (\S+)\.| ) {
$host = $1;
} else {
# Unrecognized line...reset
$get = $host = $title = '';
}
if ($get and $host) {
my ($title) = $get =~ m|^.*\/(.+?)$|; # default title
my $url = 'http://' . $host . $get;
$mech->get($url);
if ($mech->success) {
# HTML may have title, images will not
$title = $mech->title() || $title;
}
print "Title: $title\n";
print "URL: $url\n";
print "\n";
$get = $host = $title = '';
}
}
These look to be the key lines in the output from cpanm, down at the bottom.
! Installing the dependencies failed: Installed version (3.59) of CGI is not in range '4.08'
! Bailing out the installation for WWW-Mechanize-1.75.
Looks like you need to install a higher version of the CGI distribution.
The key lines in the cpanm output are:
Building and testing CGI-4.21 ... FAIL
! Installing CGI failed. See /Users/skylerspaeth/.cpanm/work/1440436409.90704/build.log for details. Retry with --force to force install it.
So look in /Users/skylerspaeth/.cpanm/work/1440436409.90704/build.log and see what the problem is. If that log is no longer there, you may need to run cpanm again, which will generate another build.log.
You find the key lines in cpanm output by searching for "fail". Usually, it'll point you at a build.log file for further details.

How can I do inplace editing (-i) with perl on windows?

In the unix/linux version, I'd simply change the first line:
#!perl -i.bak
Using Activestate perl on windows, where I've created the association with .pl, I can run a perl script directly from the command line.
myScript.pl
How can I do inplace editing of files if I still want to use the default association?
Sounds like a trick question, and I wonder if I am understanding you right.
perl -pi.bak myScript.pl myfiletochange
Just call perl, supply the switches and the script name, and off you go.
Now, it may be that you do not want to supply these extra arguments. If so, you can simply set the variable $^I, which will activate the inplace edit. E.g.:
$^I = ".bak"; # will set backup extension
Since you are going to be using a script you might want to do something like this:
sub edit_in_place
{
my $file = shift;
my $code = shift;
{
local #ARGV = ($file);
local $^I = '';
while (<>) {
&$code;
}
}
}
edit_in_place $file, sub {
s/search/replace/;
print;
};
if you want to create a backup then change local $^I = ''; to local $^I = '.bak';

Resources