Wednesday, December 2, 2009

AutoIT: Mimic User Activities with Files

There was a need for us to perform some user activities while our servioces were running on a system. The activities would be pertaining to file and as below:
1. Opening an instance of excel, winword or wordpad.
2. Writing some text in the opened instance.
3. Saving the file with a filename on the C:\


Script:

Here's the AutoIT script that would perform the above mentioned operations in an excel sheet.

; Run Excel
Run("C:\Program Files\Microsoft Office\Office12\Excel.exe")

WinWaitActive("Microsoft Excel - Book1")
sleep(500)
Send("{F2}")
sleep(500)
;writing into excel
$i = 0
Do
Send("=rand()")
Send("{ENTER}")
$i = $i + 1
Until $i = 500

; Finished!

;saving the document
Send("!f")
sleep(500)
Send("a")
WinWaitActive("Save As")
sleep(500)
Send("C:\Excel")
Send("{ENTER}")
sleep(1000)
Send("!{F4}")



Friday, November 20, 2009

Auto Refresh

Half an hour ago I felt a need for refreshing my web page as the same used to time out every 20 minutes, if not refreshed.
I bet all of you must have faced this situation someday at your work or while browsing at home. Isn't it? Surely, if you are a customer of icicidirect.com. :-)

Here's something on the solution front:
Raghu and I arrived at 2 solutions, of course, as you must have guessed, they are browser dependent.

Let’s begin with IE:
There is a website called: http://www.pagereboot.com/ie/ that comes to our rescue.
For eg:
http://www.pagereboot.com/ie/?url=http://www.rediff.com/&refresh=5
Above URL can be divided into three components:
1. http://www.pagereboot.com is the host website.
2. www.rediff.com webpage that you want to refresh and keep it alive.
3. &refresh=5 that helps you to refresh every 5 seconds.
Points 2 and 3 would be parameters and can be configured based on requirements.

Trivial! Isn’t it?

Let’s check out Firefox:
Here are a few easy steps that can help you on a FF browser.
1. Go to Firefox browser instance and go to Tools -> Add-Ons.
2. Add-Ons -> Get Add-Ons and search for ReloadEvery.
3. Click on Add to Firefox button and let the plug-in get installed.
4. The browser would now automatically restart.
5. Open your webpage on the browser instance and right click on the page.
6. You would now see a new option getting added in the menu that says ‘Reload Every’.
7. Configure it as per your use and Enjoy!

Lengthier, but simple and clean.

Up to you, you can use any one....

Let us know if you find a cooler way!

Friday, September 25, 2009

PERL: Check dlls used in a process

Problem Statement:
Find whether named dll’s are injected into certain processes

Solution:
Perl script (CheckDllInjection.pl) would:
Read a configuration xml
Start monitoring the processes (added in the process tags) and
Check if the dlls (added in dll tags) are getting injected in these processes or not.
Report the results in a desired format.

Pre-requisites:
You need to have Perl installed on your system and XML::Simple module should be present.

Input:
DllConfig.xml would contain the processes (Process tag) to be monitored and the dll’s (Dll tags) that need to be checked for injection. (sample Dllconfig.xml attached). Perl script to be run from a location where dll file is present.

Output:
Output is a Results.csv file that would give out the results telling if the dlls were really injected in the processes with the values as YES/NO and results as PASS/FAIL.

Contents of DllConfig.xml file:

<configuration>
<test>
<test1>
<process>process1.exe</process>
<dll>abc.dll</dll>
<dll>xyz.dll</dll>
</test1>

<test2>
<process>process2.exe</process>
<dll>pqr.dll</dll>
<dll>lmnop.dll</dll>
<dll>cjg.dll</dll>
</test2>
</test>
</configuration>

Perl Script that works on Windows Platform:

#!/usr/bin/perl
use XML::Simple;
if(-e "Results.csv")
{
system "del Results.csv";
}
open(FP, "> Results.csv");
print FP "Process,DLL,Injected?,Result \n";

$xml = new XML::Simple;
$dllconfig = $xml->XMLin("DllConfig.xml"); #reached the Configuration tag
$test = $dllconfig->{Test}; #reached the Test tag
%tests = %$test;

#got all the processes and dlls
$count=0;
foreach my $k (keys %tests) {
$process = $test->{$k}->{Process};
$dll = $test->{$k}->{Dll};
if(ref($dll) eq 'ARRAY')
{
foreach $mydll (@$dll) #reading DLL files one by one
{
system "tasklist /M $mydll > C:\\$mydll.txt";

open(FH, "C:\\$mydll.txt");

$size = -s FH;
if(!$size) { print FP "$process,$mydll,NO,FAIL\n";}

while()
{
if($_ =~ m/.*$process.*/i)
{
print FP "$process,$mydll,YES,PASS\n";
$flag=1;
last;
}
else
{
$flag=0;
}
}
if(!$flag) {print FP "$process,$mydll,NO,FAIL\n";}
close FH;
system "del c:\\$mydll.txt";
}

}
else
{
system "tasklist /M $dll > C:\\$dll.txt";

open(FH, "C:\\$dll.txt");

$size = -s FH;
if(!$size) { print FP "$process,$dll,NO,FAIL\n";}

while()
{
if($_ =~ m/.*$process.*/i)
{
print FP "$process,$dll,YES,PASS\n";
$flag=1;last;
}
else
{
$flag=0;
}

}if(!$flag) {print FP "$process,$dll,NO,FAIL\n";}
close FH;
system "del c:\\$dll.txt";
}
}

close FP;

Monday, August 3, 2009

PERL: Testing a Web Service

Problem Statement: Testing a Web Service

Here's a small script that you can use for testing a Web Service.

#!/usr/bin/perl


use LWP::UserAgent;
use HTTP::Request;


TestWS();

sub TestWS
{

my $message = "Your Request Message";

my $userAgent = LWP::UserAgent->new();
my $request = HTTP::Request->new(POST => "Link of the WebService");
$request->header(SOAPAction => '"Soap Header that is being used"');
$request->content($message);
$request->content_type("text/xml; charset=utf-8");
my $response = $userAgent->request($request);

if($response->code == 200)
{
print "Web Service works fine";
}

else
{
print "Looks like there is a bug in the web service";
}
}


By posting the request message and getting the HTTP response back with the help of useragent would help us test the Web Service.


Getting performance of Web Service:

This can be done by keeping the method TestWS() in a for loop and logging the response in a log file along with the date.

So, keeping everything same as above, we create a file C:\WSlog.log file and run a while loop for TestWS method. Also we log the time every time we get a response as depicted in the change script below.


open (FP, ">C:\\WSlog.log");

while(1)
{
&TestWS();
}

Change in the script:
if($response->code == 200)
{
$x = gmtime();
print FP "$x";
print FP $response->as_string;

}

Analyzing the log file:
Finding the no. of requests and responses taht we have received, we can get the time frame in which a response is made from the Web Service.

Also while running this script, after sometime we would observe 500 Internal Server Error. That is the point we say teh Web Service has run out of sockets for communication. Hence we get a limit on teh no. of continous requests that can be made to a Web Service.

Monday, June 29, 2009

PowerShell: MD5/SHA1 hashes of files

Problem Statement: I need to get Signatures (MD5 and SHA1) of all the files present at a certain location on the hard disk.
Utility: This could be for checking the signature of the files present in the downloaded build for correctness or if need be for whitelisting of files.
Here's a small PowerShell script

function Get-Md5{
param ($file)
$input = get-content -encoding byte -readcount -1 $file$md5 = [System.Security.Cryptography.MD5]::Create()
$output = $md5.ComputeHash($input)$sb = new-object Text.StringBuilder
foreach ($b in $output) {
[void] $sb.Append($b.ToString("X2"));
}
$sb.ToString()
}function Get-SHA1{param ($file)
$input = get-content -encoding byte -readcount -1 $file$sha1 = [System.Security.Cryptography.SHA1]::Create()
$output = $sha1.ComputeHash($input)
$sb = new-object Text.StringBuilder
foreach ($b in $output) {
[void] $sb.Append($b.ToString("X2"));
}
$sb.ToString()
}
"MD5`tSHA1`tFilePath" out-file C:\Hashes.xls -append$files = get-childitem $args -recurse -include *.*
foreach ($i in $files) {
$md5 = get-md5 $i $sha1 = get-sha1 $i "$md5`t$sha1`t$i" out-file C:\Hashes.xls -append
}
Hope this helps.

Tuesday, May 26, 2009

Batch: '-' issues

Today, I encountered something unusual at work.

~ I had an application (say app.exe) that accepted parameters; for e.g., if "App.exe -i" command is executed, the application would get installed on the system.
~ Also, I had a BATCH script that would call App.exe with options for further processing.
But somehow the script didn't run effectively. I had to use the command, "App.exe -i" in the script and when I ran the script, to my surprise, I could see the command being executed as "App.exe ϋi" instead of "App.exe -i". That is, instaed of "-" it ran as "ϋ" on the command prompt.
Where did this "ϋ" come from??

After struggling for an hour or so I could gauge that the "ϋ" sign was because of the space between App.exe and -i in the command.

The simple solution was to use a ESCAPE sequence before the space. Hence I scripted the command as "App.exe^ -i". where ^ is the escape sequence in DOS and then space was no more an issue.

Interesting isn't it!! :-)

Wednesday, April 1, 2009

Powershell-GUI: EventLog Manager

Problem Statement: Recently. there was a requirement for me to clear or save event logs of different systems on the network. The number of systems in the network were at least 10 and the requirement demanded that I had to Save Event logs or Clear Event Logs on all/selected servers (separated by commas), in one go!



Now here's what I came up with:






Script:
Function Main{
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
$form = New-Object Windows.Forms.Form $form.text = "Event Log Manager"
$form.height = 400
$label_logname = New-Object Windows.Forms.Label
$label_logname.Location = New-Object Drawing.Point 50,30
$label_logname.Size = New-Object Drawing.Point 200,30
$label_logname.text = "Enter the EventLog Name"
$combo = new-object System.Windows.Forms.ComboBox
$combo.Location = new-object System.Drawing.Size(50,60)
$combo.Size = new-object System.Drawing.Size(200,15)
$combo.Items.Add("Enter EventLog") $combo.Items.Add("Application")
$combo.Items.Add("System")
$label_server = New-Object Windows.Forms.Label
$label_server.Location = New-Object Drawing.Point 50,110
$label_server.Size = New-Object Drawing.Point 200,30
$label_server.text = "Enter the Server Names separated by commas"
$combo1 = new-object System.Windows.Forms.ComboBox
$combo1.Location = new-object System.Drawing.Size(50,150)
$combo1.Size = new-object System.Drawing.Size(200,15)
$combo1.Items.Add("10.2.2.3")
$button = New-Object Windows.Forms.Button
$button.text = "Save EventLog"
$button.Location = New-Object Drawing.Point 50,200
$button.Size = New-Object Drawing.Point 200,25
$button1 = New-Object Windows.Forms.Button
$button1.text = "Clear EventLog"
$button1.Location = New-Object Drawing.Point 50,250
$button1.Size = New-Object Drawing.Point 200,25
$button2 = New-Object Windows.Forms.Button
$button2.text = "Quit..."
$button2.Location = New-Object Drawing.Point 50,300
$button2.Size = New-Object Drawing.Point 200,25
$button.add_click({ $form.hide()
SaveEvtLog $combo1.text $combo.text })
$button1.add_click({ $form.hide()
ClearEvtLog $combo1.text $combo.text })
$button2.add_click({ $form.dispose() })
$form.controls.add($button)
$form.controls.add($label_logname)
$form.controls.add($label_server)
$form.controls.add($button1)
$form.controls.add($button2)
$form.controls.add($combo)
$form.controls.add($combo1)
$form.ShowDialog()
}

Function SaveEvtLog {
param ($computer,$evtlog)
$servers = $computer.split(',')
foreach ($server in $servers) {
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
$form1 = New-Object Windows.Forms.Form $form1.height = 300 $form1.width = 300 $label2 = New-Object Windows.Forms.Label
$label2.Location = New-Object Drawing.Point 50,30
$label2.Size = New-Object Drawing.Point 200,90
$ALive=get-wmiobject win32_pingstatus -Filter "Address='$server'" Select-Object statuscode
if($ALive.statuscode -ne 0)
{ "Host $server is Unreachable...`n" out-file log.txt -append }
else { $filename = "Log_" + $evtlog + "_" + $server + ".evt"
if((Test-Path -path c:\$filename) -ne $False) { remove-item C:\$filename } wmic /node:"$server" nteventlog where "logfilename='$evtlog'" call backupeventlog "C:\$filename" out-file null
remove-item null
copy-item file://$server/c$/$filename C:\
remove-item file://$server/c$/$filename
$lbl_text = "EventLog copied at c:\$filename" out-file log.txt -append } }
$lbl = get-content log.txt
$label2.text = $lbl
$button4 = New-Object Windows.Forms.Button
$button4.text = "Back to Main..."
$button4.Location = New-Object Drawing.Point 50,180
$button4.Size = New-Object Drawing.Point 200,25 remove-item log.txt
$button4.add_click({ $form1.hide()
Main })
$form1.controls.add($label2)
$form1.controls.add($button4)
$form1.ShowDialog() }

Function ClearEvtLog {
param ($computer,$evtlog)
$servers = $computer.split(',')
foreach ($server in $servers) {
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
$form1 = New-Object Windows.Forms.Form
$form1.height = 300 $form1.width = 300
$label2 = New-Object Windows.Forms.Label
$label2.Location = New-Object Drawing.Point 50,30
$label2.Size = New-Object Drawing.Point 200,90
$ALive=get-wmiobject win32_pingstatus -Filter "Address='$server'" Select-Object statuscode
if($ALive.statuscode -ne 0)
{ "Host $server is Unreachable...`n" out-file evt.txt -append }
else { $logs = [System.Diagnostics.Eventlog]::GetEventLogs("$server")
$Applogs = $logswhere-object {$_.logdisplayname -eq "$evtlog" }
if($Applogs -ne $null)
{$Applogs.clear()
"$evtlog Event Log Cleared at $server `n" out-file evt.txt -append}
else {"Event log is already cleared or it doesnt exist `n" out-file evt.txt -append} } } $lbl = get-content evt.txt
$label2.text = $lbl
$button4 = New-Object Windows.Forms.Button
$button4.text = "Back to Main..."
$button4.Location = New-Object Drawing.Point 50,180
$button4.Size = New-Object Drawing.Point 200,25 remove-item evt.txt
$button4.add_click({ $form1.hide()
Main })
$form1.controls.add($label2)
$form1.controls.add($button4)
$form1.ShowDialog() }

Main



Hope this helps!! Let me know your comments...

PERL: Base64 Encoding

What is Base64: Base64 is MIME character tranafer encoding...Its like any other encoding that uses a-zA-Z0-9/+ (64 characters and = for padding) for converting the string...An important encoding format....Between, have you wondered if we could use a Base64 encoded string as a filename?? Think??

Here's a small PERL script that would help you in encoding and decoding the input string:

C0de:
#! /usr/bin/perl
use MIME::Base64;
print "Enter the Choice\n";
print "1. Encode to Base 64\n";
print "2. Decode from Base64\n";print "Enter the choice::";
my $choice=<STDIN>;
if($choice==1)
{ print "Please enter a string that is to be encoded:"; my $str=; my $encode=encode_base64($str); print "String ENCODED as:$encode"; }
if($choice==2)
{ print "Please enter a Base 64 string that is to be decoded:"; my $str=; my $decode=decode_base64($str); print "String DECODED as:$decode"; }

Hope this helps!!!

PowerShell: Script for getting the inventory details....

Hya!! After a long gap, I am here again...
This time I have come up with an utility that takes the details of your inventory.

Problem Statement: I have a lot of servers on my network and my manager comes and tell me, "Can you get me details like the total RAM, HDD, Manufacturer, Serial Number and ServerName of all these servers?? I need to report this to Infrastructure team! Please get this in 2 hours time!!" Sounds laborious..Isn't it??

Here's the script:

"IP`tHardDisk`tRAM`tSystemName`tManufacturer`tSerialNumber" out-file C:\Results.csv -append

Function HDDInfo { param($ip) $alldrives = get-wmiobject win32_logicaldisk -filter "DriveType=3" -computername $ip $HDD = 0 foreach ($i in $alldrives) { $HDD = $HDD + ($i.size)/(1gb) } $HDD }

Function RAMInfo { param($ip) $ram = get-wmiobject win32_ComputerSystem -computername $ip $RAM = ($ram.TotalPhysicalMemory)/(1gb) $RAM }

Function SystemName { param($ip) $bios = get-wmiobject win32_bios -computer $ip $bios.name }

Function Manufacturer { param($ip) $bios = get-wmiobject win32_bios -computer $ip $bios.manufacturer } Function SerialNumber { param($ip) $bios = get-wmiobject win32_bios -computer $ip $bios.SerialNumber }

$address = "10.2.2."
2..254 foreach-object { $ip = $address + $_
$ping = get-wmiobject win32_pingstatus -filter "Address = '$ip'" select-object statuscode
if($ping.statuscode -eq 0) { $HDD = HDDInfo $ip sleep 1 $RAM = RAMInfo $ip sleep 1 $SystemName = SystemName $ip $Manufacturer = Manufacturer $ip $SerialNumber = SerialNumber $ip
"$ip`t$HDD`t$RAM`t$SystemName`t$Manufacturer`t$SerialNumber" out-file C:\Results.csv -append } else { "$ip is Offline or Not Reachable.." out-file C:\Results.csv -append }
}


In this script, I assume all your systems on the network are in the IP range of 10.2.2.x and I am collecting the details of IPs: 10.2.2.2 - 10.2.2.254

Run the script, wait for 4-5 minutes and get the results in Results.csv file. :-)

Hope this helps!!

Friday, February 13, 2009

PowerShell: OS Statistics for a Remote Host

Here's a small PowerShell Script that would enable you to get the OS Statistics for a Host...
----------OS-Statistics.ps1------------------
Function Main {
# Load the Winforms assembly
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
# Create the form
$form = New-Object Windows.Forms.Form
#Set the dialog title
$form.text = "OS Statistics"














# Create the label control and set text, size and location
$label = New-Object Windows.Forms.Label
$label.Location = New-Object Drawing.Point 50,50
$label.Size = New-Object Drawing.Point 200,15
$label.text = "Enter Hostname"

$combo = new-object System.Windows.Forms.ComboBox
$combo.Location = new-object System.Drawing.Size(50,80)
$combo.Size = new-object System.Drawing.Size(200,25)
$combo.Items.Add("ComputerName / IP")
$combo.Items.Add("192.168.219.")
$combo.Items.Add("127.0.0.1")

# Create Button and set text and location
$button = New-Object Windows.Forms.Button
$button.text = "Get OS Statistics"
$button.Location = New-Object Drawing.Point 50,130
$button.Size = New-Object Drawing.Point 200,25

$button3 = New-Object Windows.Forms.Button
$button3.text = "Quit...."
$button3.Location = New-Object Drawing.Point 50,180
$button3.Size = New-Object Drawing.Point 200,25

# Set up event handler to extarct text from TextBox and display it on the Label.
$button.add_click({ NewForm $combo.text })
$button3.add_click({ $form.dispose() })

# Add the controls to the Form
$form.controls.add($button)
$form.controls.add($button3)
$form.controls.add($label)
$form.controls.add($combo)

# Display the dialog
$form.ShowDialog()
}

Function NewForm
{
Param ($ip)

$ALive=get-wmiobject win32_pingstatus -Filter "Address='$ip'" Select-Object statuscode
if($ALive.statuscode -ne 0)
{
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
$form1 = New-Object Windows.Forms.Form
$form1.height = 180
$label1 = New-Object Windows.Forms.Label
$label1.Location = New-Object Drawing.Point 50,10
$label1.Size = New-Object Drawing.Point 200,50
$label1.text = "Sorry!! The Host is Unreachable `n`n Check if" + $ip + " is Online..."
$button2 = New-Object Windows.Forms.Button
$button2.text = "Click to Get Back"
$button2.Location = New-Object Drawing.Point 50,80
$button2.Size = New-Object Drawing.Point 200,25
$button2.add_click({
$form1.dispose()
})
$form1.controls.add($button2)
$form1.controls.add($label1)
$form1.showdialog()
}
























else{
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
$form1 = New-Object Windows.Forms.Form
$form1.height = 600
$form1.width = 300
$label1 = New-Object Windows.Forms.Label
$label1.Location = New-Object Drawing.Point 50,10
$label1.Size = New-Object Drawing.Point 200,600
$perf= get-wmiobject Win32_PerfFormattedData_PerfOS_System -computer $ip
$uptime=$perf.SystemUpTime/3600
$freedisk = get-wmiobject win32_logicaldisk -filter "DriveType=3" -computer $ip foreach-object {"`n{0} {1}" -f $_.DeviceID,($_.freespace/1gb)}
$result = "`n--------------------------------------------`n" + "OS STATISTICS :: " + $ip + "`n--------------------------------------------`n`n" + "Processes:`t" + $perf.Processes + "`n`nThreads:`t" + $perf.Threads + "`n`nSystem UpTime In hours:`t" + $uptime + "`n`nAlignment Fixups/sec:`t" + $perf.AlignmentFixupsPersec + "`n`nContext Switches/sec:`t" + $perf.ContextSwitchesPersec + "`n`nException Dispatches/sec:`t" + $perf.ExceptionDispatchesPersec + "`n`nFile Control Bytes/sec:`t" + $perf.FileControlBytesPersec + "`n`nFile Control Operations/sec:`t" + $perf.FileControlOperationsPersec + "`n`nFile Data OperationsPersec:`t" + $perf.FileDataOperationsPersec+ "`n`nFile Read Bytes/sec:`t" + $perf.FileReadBytesPersec + "`n`nFile Read Operations/sec:`t" + $perf.FileReadOperationsPersec + "`n`nFile Write Bytes/sec:`t"+ $perf.FileWriteBytesPersec +"`n`nFile Write Operations/sec:`t" + $perf.FileWriteOperationsPersec + "`n`nSystem Calls/sec:`t"+ $perf.SystemCallsPersec + "`n`nFree Disk Space in GB:`n" + $freedisk
$label1.text = "$result"
$button1 = New-Object Windows.Forms.Button
$button1.text = "Click to Get Back"
$button1.Location = New-Object Drawing.Point 50,520
$button1.Size = New-Object Drawing.Point 200,25
$button1.add_click({
$form1.dispose()
})
$form1.controls.add($button1)
$form1.controls.add($label1)
$form1.showdialog()
}

}

Main

Monday, February 9, 2009

PowerShell<->Perl: Reading UNICODE files

Problem Statement:
Recently, I faced a tricky situation at work. I had a CSV file generated out of a PowerShell script. I was trying to read the CSV file and generate a graph using Perl TK module. To my surprise, no value from the CSV file got plotted on the graph! Why would this happen?

Reason:

After some tussle, I found that, this was because PowerShell generated the CSV file in a UNICODE format. PERL opens the Unicode file but can’t recognize the content. This is because “Unicode format is not a character encoding”. Hence the issue!

Resolution:
In such cases, one needs to open the Unicode files using any other Perl supported encoding format. Say, we open the file as:
Open (FH, “<:utf-8”, “filepath”);
OR
Open (FH, “<:encoding(utf-8)”, “filepath”);

Thus, Unicode text files are read exactly the same way that other files are read: by specifying a text encoding.

Wednesday, February 4, 2009

PowerShell: Ensure Successful Build Installation

Here’s one problem statement. Let’s say, you have an application installed on multiple systems i.e.; more than 1 system. And you need to know, the files that get installed on these systems once you have installed the application. To top it, the application gets installed on either C: or D: How do you do this? In PowerShell it’s easy.

Code:
Disclaimer: I’m not responsible for any inadvertent consequences you face after running this script.
Below, ‘test’ is the folder where the application gets installed.
FileName: Files-AfterInstall.ps1

foreach ($computer in $args)
{
"-----------------" | out-file BuildInstalled.txt -append
"$computer" | out-file BuildInstalled.txt -append
"-----------------" | out-file BuildInstalled.txt -append

if ((Test-Path -path \\$computer\c$\test) -ne $True)
{}
else
{
get-childitem -recurse \\$computer\c$\test -include *.* | foreach-object {$_.FullName} | out-file BuildInstalled.txt -append
}

if ((Test-Path -path \\$computer\d$\test) -ne $True)
{}
else
{
get-childitem -recurse \\$computer\d$\test -include *.* | foreach-object {$_.FullName} | out-file BuildInstalled.txt -append
}

}

Run as: .\Files-AfterInstall.ps1 system1 system2 (system1, system2 ... system n are the systems where build is installed)

Output:
As output, you would receive a file named BuildInstalled.txt which gets created where the script is running. This file would contain the full path of the files that get installed.

Monday, February 2, 2009

PowerShell: GetFileVersion Information as Build Verification Test

As a Dev or QA, we often are worried about the FileVersion information being present on the binaries that we develop and that are shipped to customers. Here’s a small PowerShell script that would help in finding whether we have the fileversion data on all the binaries or not (Currently it checks for .exe and .dll files). Those who know a bit of programming would definitely be able to customize the script as per their requirement.

Please run this carefully. I’m not responsible for any inadvertent consequences.

$files = get-childitem $args -recurse -include *.dll,*.exe
if($files -eq $null)
{
Write-Host "No Exe or dll files present in the folder";
}
else
{
foreach ($i in $files)
{
$ver = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($i).FileVersion
if($ver -eq $null)
{
$i.FullName Out-File NoVersion.txt -append
}
else
{
"{0}`t{1}"-f $i.FullName, [System.Diagnostics.FileVersionInfo]::GetVersionInfo($i).FileVersion out-file Version.xls -append
}
}
}

Run as:
If the above code is copied in a file named: Build-FileVersion-Info.ps1
.\ Build-FileVersion-Info.ps1 FolderName FolderName - is the build folder

Output:
1. We have a file called Version.xls as output that would give the filepaths and fileversion of all the binaries that have fileversion information.
2. Output is also a Noversion.txt file that would give the filepaths of the files that have no fileversion.
3. Output can also be No Exe or dll files present in the folder, which should be self explanatory.

Hope this was useful!!

Monday, January 19, 2009

PowerShell: Issues with GetEventLog on Windows XP

Enough of PERL for the time being......

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…”)

** Before starting, I am not responsible for the ramifications you face after running the below mentioned scripts...So be contemplative before trying these out!! **

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 : bytes=32 time<1ms TTL=128 – PING successful, host reachable
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!!