Lookout for scripting experiences, automated tools and frameworks that I develop....
Monday, January 19, 2009
PowerShell: Issues with GetEventLog on Windows XP
Something in PowerShell now!
** Before starting, I am not responsible for the ramifications you face after running the below mentioned scripts...So be contemplative before trying these out!! **
Of late I have been working on Windows PowerShell and here’s one of my observations on Windows XP OS. – assuming that you have a XP system with PowerShell for XP running on it.
Following is the command that one would use in PowerShell for getting all the Event Logs of a remote system on the network.
$logs = [System.Diagnostics.EventLog]::GetEventLogs('HostName or IP')
Now, if you key in the command:
$logs
The output that you get would be something like this:
Max(K) Retain OverflowAction Entries Name
------ ------ -------------- ------- ----
512 7 OverwriteOlder 2,130 Application
512 7 OverwriteOlder 0 Internet Explorer
16,384 0 OverwriteAsNeeded 0 Microsoft Office Diagnostics
16,384 0 OverwriteAsNeeded 2,960 Microsoft Office Sessions
512 7 OverwriteOlder 0 Security
512 7 OverwriteOlder 2,337 System
15,360 0 OverwriteAsNeeded 40 Windows PowerShell
The interesting thing here is: What happens if the hostname in the first command is “localhost”?
Well in Win2k3 – STD/ENT and x86/x64 versions of OS, this would work fine giving you the correct output. But if the same command is run on the XP machine, that is, if the following is run on variants of XP OS, you would encounter an error.
------------------------------------------------------------------------------------------------
$logs = [System.Diagnostics.EventLog]::GetEventLogs('localhost')
Exception calling "GetEventLogs" with "1" argument(s): "The network path was no
t found.
"
At line:1 char:52
+ $logs = [System.Diagnostics.EventLog]::GetEventLogs( <<<< 'localhost')
----------------------------------------------------------------------------------------------
Looks like there’s an issue with ‘localhost’ on XP.
Solution:
There’s a way to get the event log of local system while running on Windows XP. Here’s what would work: $logs = [System.Diagnostics.EventLog]::GetEventLogs('127.0.0.1'). so instead of localhost, you could run the same with 127.0.0.1. Simple! But, a bit less obvious. Definitely, giving the ‘ComputerName’ or ‘IP’ itself would work.
Monday, January 5, 2009
PERL: Using return type of System(“ping…”)
Problem Statement:
I had taken up an initiative of scripting an application that required me to ping a certain host that is keyed in by the user and if the host was PING able (that is if I could get a reply to my ICMP request), I had to start some tests on the same host.
Approach #1:
As you would know, after a PING command we have two kinds of outputs:
a. Reply from
b. Request timed out. – Unreachable host, PING unsuccessful
So my plan was to ping the host in the script and redirect the output of the ping request on to a file. If the redirected file contents happen to be one of these, that is either it matched “Reply from” or it matched “Request timed out”, then the host is PING able or not. Looks easy! But while implementing this logic, you need to open up a file (containing the redirected output), search for contents, match the lines with certain keywords (Reply from or Request timed out) and then decide further. It works, but at the same time it’s painful! I bet you would agree. So I thought of looking out for other options.
Approach #2:
Here’s what struck to me. How about using the return-type of PING? Actually, if you browse through some websites, you would understand that there are 3 return-types of PING.
a. 0 for successful ping
b. 1 if there is any fault in the way the ping request was sent i.e., corrupted packets
c. 2 for unreachable host
Actually, when I devised the trick that I am going to reveal now, I wasn’t thinking about these 3 return types. I simply tried this code:
Code:
use strict;
my $ping = system "ping hostname"; #replace hostname with your IP or Computer name
if(!$ping)
{
print "PING returned: $ping...Host Reachable!!";
}
else
{
print "PING returned: $ping...Host Unreachable!!";
}
#Line 3: if the host is reachable $ping has value of “0”. So using “!$ping”
Execution of the script:
When I ran this code snippet on WinXP and Win2k3 servers, I got the following results:
1. For Reachable IPs: PING returned: 0...Host Reachable!!
2. For Unreachable IPs: PING returned: 256...Host Unreachable!!
You would have realized that, if the host is contactable, the variable $ping contains a value 0 and if not then it stores value of 256. This is the trick secret!!
Approach #3:
This approach is the easiest one and an orthodox one. But you don’t learn anything here. Try using Net::Ping module available in PERL to check if the host is ping able. But again it involves 2 lines of code to understand if the host is reachable unlike 2nd approach!
Code:
$p = Net::Ping->new();
print "$host is alive.\n" if $p->ping($host);
Epilogue:
Out of the 3 approaches, I would go in for the second one; of course as I found it. But I am unsure at this point of time that, whether the return type was of PING or of System function? Anyhow, this consistently works in PERL code run on Windows platform that I mentioned. Let me know your thoughts!!
Sunday, December 21, 2008
PERL: Making Ctrl+C ineffective
** Before starting, I am not responsible for the ramifications you face after running the below mentioned scripts...So be contemplative before trying these out!! **
If you have been using PERL for a long time now, you must be cognizant of the fact that, if you see your program behaving in an unexpected/bizarre way, pressing Ctrl+C would help you to stop the program execution. But did you know, you can disable this functionality. By disable, I mean that, even after pressing Ctrl+C, your program won’t stop executing. Sure, this would have kindled your thinking caps!! Let’s see how we can achieve it.
This could be easily accomplished by scripting a single line at the onset of your program.
$SIG{‘INT’} = ‘IGNORE’;
But how do you check it? For checking, try this piece of code:
$SIG{'INT'} = 'IGNORE';
@arr = (0..10);
foreach (@arr) {
print("$_\n");
sleep 1;
}
While the code snippet is getting executed, if you pres Ctrl+C, it would not stop your program.
This worked on Windows XP for me....Cool!! Isn’t it??
Let’s say, instead of ignoring Ctrl+C, you want to achieve something else when Ctrl+C is pressed. Like, say you want the program to print some message or exit. This is how it can be done:
sub INT_handler { #function starts
print("Don't Interrupt!\n");
#exit(0); - similar to print, program can be exited using exit(0)
}
$SIG{'INT'} = 'INT_handler';
@arr = (0..10);
foreach (@arr) {
print("$_\n");
sleep 1;
}
While the program execution happens, pressing Ctrl+C will print “Don’t Interrupt!”
But beware, if again Ctrl+C is pressed, the program execution stops.
This worked on Windows XP for me.
Underlying facts:
Basically Ctrl+C is a signal that is sent to the program. So when Ctrl+C sequence is pressed, a signal called INT is activated. When we say $SIG{‘INT’} = ‘IGNORE’, we basically ignore this signal and hence it doesn’t affect program execution.
Similar to INT, we have many more signals. In order to see these, you can run this code:
foreach (keys %SIG) #%SIG is actually a hash that stores all signals like %ENV that stores environment variables.
{ print " $_ \n"; } #lists all the signals supported by the platform.
You are now free to play around with these....Enjoy!!
Monday, December 8, 2008
PERL: Approaches for FileSize
I’ve been a great fan of all scripting languages, especially PERL (Practical Extraction and Report Language). My objective through this blog is to bring out some anomalies or rather some surprising facts that can swerve your program from the expected output.
Here’s one.
Consider a situation where you need to find out the size of a file present on the disk, say C:\test.txt.
The content of test.txt is:
-------------------------------------------------------------
Hi,”\n”
How about some interesting facts in PERL”\n”
Look at this!!!”\n”
Interesting!!”\n”
-Chetan”\n”
“\n”
-----------------------------------------------------------
Now there are two ways we approach this situation.
1. Open (FH, “< C:\\test.txt”) die $!; #open the file in read mode or exit with error code
print "Size of file (in bytes) is: ";
print –s FH; # -s options gets the size of filehandle, i.e. the file.
The output of the above snippet is: Size of file (in bytes) is: 90
2. open (FH, "< C:\\test.txt") die $!; #open the file in read mode or exit with error code
my @filecontent=
my $count =0; #initialize a counter
foreach(@filecontent) #Browsing through the file contents line by line
{
$count += length($_); #get the length of each line and add it to the counter
}
print "size of file (in bytes) is: $count"; #prints the file size.
The output here is: Size of file (in bytes) is: 84
Oh!! What’s the difference here? How come same file printing out to give different file sizes? Any wrong with the way either of programs is run? Which is the correct approach?
Explanation: The hitch here is, the function length($_) doesn’t consider the “\n” character that I have pointed out in the content of test.txt. So the 6 “\n” that are present, are not counted and hence the results differ.
But the correct size is given by the first approach as the new line character is also very much a character of the file. Now you know the next time you need to find the size of file what approach can you bank on!!