What is the best way to programatically determine if a Perl script is executing on a Windows based system (Win9x, WinXP, Vista, Win7, etc.)?
Fill in the blanks here:
my $running_under_windows = ... ? 1 : 0;
From perldoc perlvar:
$OSNAME
$^O
The name of the operating system under which this copy of Perl was built, as determined during the configuration process. The value is identical to $Config{'osname'}. See also Config and the -V command-line switch documented in perlrun.
In Windows platforms, $^O is not very helpful: since it is always MSWin32, it doesn't tell the difference between 95/98/ME/NT/2000/XP/CE/.NET. Use Win32::GetOSName() or Win32::GetOSVersion() (see Win32 and perlport) to distinguish between the variants.
$^O eq 'MSWin32'
(Source: The perlvar manpage)
Use Devel::CheckOS. It handles all of the logic and special cases for you. I usually do something like:
use Devel::CheckOS qw(die_unsupported os_is);
die "You need Windows to run this program!" unless os_is('MicrosoftWindows');
The 'MicrosoftWindows' families knows about things such as Cygwin, so if you are on Windows but not at the cmd prompt, os_is() will still give you the right answer.
This is very quick and dirty, and wouldn't bet it's 100% portable, but still useful in a pinch.
Check for presence of back slashes in the PATH Env variable, since PATH is common to both Windows and Unix.
So - in Perl:
if ( $ENV{PATH}=~m{\\} ) {
#Quick and dirty: It's windows!
print "It's Windows!";
} else {
print "It's Unix!";
}
Related
If you are in a Cygwin or MinGW bash shell, environment variables like $PATH are in "UNIX" format - using forward slashes as dir separators and using the colon to separate multiple paths. But if, inside this shell, you run something like cmd.exe /c 'echo %PATH%' the resulting output is in "Windows" format, using backslashes and semicolons respectively.
Is this magical conversion documented somewhere? Or better yet, can somebody point to the code that makes this happen?
(The reason I ask is because it seems the conversion doesn't always happen and I'm trying to understand the exact conditions needed for it to occur.)
The internal conversions between Unix and Windows path format are
performed by the funtions in path.cc
https://cygwin.com/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/path.cc;h=3cb46c9c812e17460d56def2f915b21c7227f3bf;hb=HEAD
When a Cygwin program executes a Windows program the spawn process is
performed by functions in spawn.cc
https://cygwin.com/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/spawn.cc;h=37db52608e24e866e80401668ef13562f0cb67ea;hb=HEAD
If you need more details or ask clarification use the cygwin mailing list.
With the cmd.exe, i call a programm that I have not write myself. I cannot modify it. I would like to disable the message printed in the shell by this programm.
My OS is Windows 7 enterprise 32 bits.
Thank you
If it's outputting to standard error and output, you should be just able to redirect them:
dodgy_prog >nul: 2>nul:
(or use /dev/null under UNIXy operating systems - it's unclear which variant you want since you talk about the Windows cmd.exe but your question is tagged bash).
Is there a Perl command that lets me get the minimum supported OS for any given binary?
You can manually get that information by running "link /dump /headers [binaryFile]" and looking for the "subsystem version" link. I don't want to use that since it's got really bad perf.
Thanks
If you need this for Windows, use get_manifest from Win32::Exe. You will need to install it first.
If there's a command that gets what you want, why not just run that command?
You can use backticks or qx// in Perl to get a command's output
eg:
my $output = `command arg1 arg2 ...`;
Or, if you want an array of lines:
my #lines = `command arg1 arg2 ...`;
Then you can use Perl's normal facilities for scanning that output for patterns you're interested in.
Also, your command looks like it is for Windows - is that true? If so, you should add a Windows tag.
How do you extend the output of ps -fe in Solaris so that it displays more than 80 characters? My process has several arguments and the process name could not be displayed anymore.
You can't display them with the default ps (/usr/bin/ps) which is a SVR4 regular one.
To get the full argument line, use the BSD ps (UCB = University of California at Berkeley):
/usr/ucb/ps -alxwww
We have finally fixed this in Solaris; as of Solaris 11.3 SRU 5, all original argument vectors as well as the environment variables can be retrieved from /proc. ps will now print all of the command line.
Fixed in Solaris 11.3 SRU 5
The simple answer is that there is no way to reliably acquire the full arguments to processes on Solaris for processes owned by other users. If you have root or other privileged access you can use /usr/ucb/ps on older versions, and 'pargs' or similar tools on newer versions (there is no tool which works across all versions).
Essentially Solaris stores the original args at process start time, while most other platforms allow ps to access, via some means, the contents of argv at runtime for the process. This stored-copy is in a special kernel data structure with limited (80 byte) size. This also means that it's not possible for a program to modify the args post-start as displayed by ps for useful or nefarious means.
Thus, if you need to access the command line for portable purposes, such as pid checking, you will need to choose between enforcing a short command line via hacks like launching programs controlled execp paths without absolute paths, or you will need to forgo that portable functionality on Solaris.
you can use pargs PID
it will give you more information than ps
Try ps -efl. If that doesn't work (I don't have a Solaris box handy) you can also try ps -efl | cat (as some programs check whether they're outputting to a terminal to decide on their output width).
There are two sets of options available for ps. Others will chime in with the correct names ( ( maybe BSD and SRVn)?)
With the non-options-preceded-with-a-hyphen-version, you can do
ps auxww(w?) | grep ${PID} to extend the length of the command detail that is printed (again, notice NO leading '-' option indicator).
Note that in some cases you will see a lot of environment variable assignments before the actually command, i.e. myPath=... cfgFile=... /path/to/command ... args ...
I think that 'www' in some systems will print everything, regardless how long the command is.
Finally, in my experience using ps to do a lot of crazy things, I would ocassionally have a PID and the output would display the first 6? columns, but the space reserved for the command was empty or had some sort of place holder value. I eventually found out why that was true, by searching comp.unix.shell, but it's too long ago now to be sure and I don't have access to Solaris systems right now.
I hope this helps.
Is it possible to call winrar through perl on a windows system, such as
perl -e "rar a -rr10 -s c:\backups\backup.rar #backup.lst"
If so, is there a more efficient way to do this?
I've looked up "perl -e" +winrar on google, however none of the results gave me any answer that was remotely close to what i was looking for. The system Im running this on is a Windows XP system. Im open to doing this in another language like python if its easier, however I am more comfertable with perl.
You can access the RAR facilities in Windows using the CPAN module Archive::Rar:
use Archive::Rar;
my $rar = Archive::Rar->new(-archive => $archive_filename);
$rar->Extract();
One way to execute external commands from a Perl script is to use system:
my $cmd = 'rar a -rr10 -s c:\backups\backup.rar #backup.lst';
if (system $cmd) {
print "Error: $? for command $cmd"
}
To use external applications from your Perl program, use the system builtin.
If you need the output from the command, you can use the backtick (``) or qx operator as discussed in perlop. You can also use pipes as discussed in perlipc.