Sunday, May 30, 2010

Sample of Powershell usage for displaying in IE

$oIE=new-object -com internetexplorer.application
$oIE.navigate2("About:blank")
while ($oIE.busy) {
    sleep -milliseconds 50
}
$oIE.visible=$true
$procList=ps |select-object ProcessName,Handles,NPM,PM,WS,VM,CPU,Id |convertto-html

$oDocBody=$oIE.document.documentelement.lastchild ;

#populate the document.body
$oDocBody.innerhtml=$procList 

$oDocBody.style.font="12pt Arial";
$oIE.document.bgcolor="#D7D7EA"

#Reading back from IE.
$oTBody=@($oIE.document.getElementsByTagName("TBODY"))[0] ;
foreach ($oRow in $oTBody.childNodes) 
{
   #check the 4 column(WS),and highlight it if it is greater than 5MB.
   $WS=(@($oRow.childNodes)[4].innerhtml) -as [int]  ;
   if (($ws -ne $null) -and ($WS -ge 5mb)) {
       $oRow.bgColor="#AAAAAA" ;
   }
}

#Prepare a title.

$oTitle=$oIE.document.createElement("P")
$oTitle.style.font="bold 20pt Arial"
$oTitle.innerhtml="Process List";
$oTitle.align="center" ;

#Display the title before the Table object.
$oTable=@($oIE.document.getElementsByTagName("TABLE"))[0] ;
$oDocBody.insertBefore($oTitle,$oTable) > $null;

A sample of IE automation with power shell

 
# Twitter login name or email
$username_or_email = "xxxxxxxxxxxxxxxx";
# Your twitter password
$password = "xxxxxxxxxxxx";
$url = "http://twitter.com/login";
 
# txt file containing 1 tweet per line
$tweets = Get-Content "$env:USERPROFILE\tweets.txt";
#Interval between tweets
$sleep = 60; 
 
# This is just an attempt to handle the situation where you are already logged into twitter
trap [Exception]
{
 # This will happen if you're already logged in
 if($_.Exception.Message -eq "Property 'value' cannot be found on this object; make sure it exists and is settable." -Or $_.Exception.Message -eq "You cannot call a method on a null-valued expression.")
 {
  # Try and skip this error
  continue;
 }
 else
 {
  # Fail for other Exceptions
  Write-Host -ForegroundColor Red $_.Exception.Message;
 }
}
 
# Create an ie com object
$ie = New-Object -com internetexplorer.application;
$ie.visible = $true;
$ie.navigate($url);
# Wait for the page to load
while ($ie.Busy -eq $true)
{
 Start-Sleep -Milliseconds 1000;
}
 
# Login to twitter
Write-Host -ForegroundColor Green "Attempting to login to Twitter.";
# Add login details
$ie.Document.getElementById("username_or_email").value = $username_or_email;
$ie.Document.getElementById("session[password]").value = $password;
# Click the submit button
$ie.Document.getElementById("signin_submit").Click();
# Wait for the page to load
while ($ie.Busy -eq $true)
{
 Start-Sleep -Milliseconds 1000;
}
 
# Loop through each tweet in the txt file
foreach($tweet in $tweets)
{
 $ie.Document.getElementById("status").value = $tweet;
 $ie.Document.getElementById("status_update_form").Submit();
 Write-Host -ForegroundColor Green "Tweeted; $tweet.";
 Start-Sleep -Seconds $sleep;
 # Check to see if ie is still busy and sleep if so
 while ($ie.Busy -eq $true)
 {
  Start-Sleep -Milliseconds 1000;
 }
}

Template for IE automation with PowerShell

<#
    .SYNOPSIS 
      Validates application login userid and password from a given excel sheet
    .EXAMPLE
     validateLogin users.xls
     This command picks userid and password from given excel sheets and validates from given URL
#>
#Set-PSDebug -trace 2 # Debug Information
#Set-PSDebug -step # Debug using stepping


if ($args) 
{
 throw "USAGE: validateLogin users.xls"
}

function openExcel($args)
{
 $xl = new-object -com Excel.Application
 foreach ( $wbk in $args )
 {
  foreach ($user in $users)
  {
   $xl.Workbooks.open($args) | out-null  #drop the object info output
   $xl.Cells.Item(1,1).Value()
   $xl.Cells.Item(3,3).Value()
   $xl.Cells.Item(6,8).Value()
   $xl.Workbooks.Close()
  }
 }
}


Function NavigateTo([string] $url, [int] $delayTime = 100)
{
  Write-Verbose "Navigating to $url"
  
  $global:ie.Navigate($url)
  
  WaitForPage $delayTime
}

Function WaitForPage([int] $delayTime = 100)
{
  $loaded = $false
  
  while ($loaded -eq $false) {
    [System.Threading.Thread]::Sleep($delayTime) 
    
    #If the browser is not busy, the page is loaded
    if (-not $global:ie.Busy)
    {
      $loaded = $true
    }
  }
  
  $global:doc = $global:ie.Document
}

Function SetElementValueByName($name, $value, [int] $position = 0) {
  if ($global:doc -eq $null) {
    Write-Error "Document is null"
    break
  }
  $elements = @($global:doc.getElementsByName($name))
  if ($elements.Count -ne 0) {
    $elements[$position].Value = $value
  }
  else {
    Write-Warning "Couldn't find any element with name ""$name"""
  }
}

Function ClickElementById($id)
{
  $element = $global:doc.getElementById($id)
  if ($element -ne $null) {
    $element.Click()
    WaitForPage
  }
  else {
    Write-Error "Couldn't find element with id ""$id"""
    break
  }
}

Function ClickElementByName($name, [int] $position = 0)
{
  if ($global:doc -eq $null) {
    Write-Error "Document is null"
    break
  }
  $elements = @($global:doc.getElementsByName($name))
  if ($elements.Count -ne 0) {
    $elements[$position].Click()
    WaitForPage
  }
  else {
    Write-Error "Couldn't find element with name ""$name"" at position ""$position"""
    break
  }
}

#Entry point
#$verbosePreference = "SilentlyContinue"
$verbosePreference = "Continue"

$global:ie = New-Object -com "InternetExplorer.Application"
$global:ie.Navigate("about:blank")
$global:ie.visible = $true
$global:ie.children



#NavigateTo "http://www.bing.com"
#SetElementValueByName "q" "powershell variable scope"
#ClickElementById "sb_form_go"
#Can also do: ClickElementByName "go"

#NavigateTo "http://mail.com"
Write-Host -ForegroundColor Green "Attempting to login to Web Application.";
#SetElementValueByName "login1" "xxx@yyy.com"
#SetElementValueByName "password" "password"
#SetElementValueByName "lr" "lang_en"
#ClickElementById "btnSignIn"

function validate
{
 begin{
  #All init for this function
 }

 process{
  #All process function
 }

 end{
  #All finilazers
 }
}

Saturday, May 29, 2010

Windows Macros with WSH

http://www.icpug.org.uk/national/features/030316fe.htm
Eg.
Dim Wsh
Set Wsh = Wscript.CreateObject("Wscript.Shell")
Wsh.AppActivate "Exploring"
Wsh.SendKeys "{F2}{END}{LEFT}{LEFT}{LEFT}{LEFT}{BS}{BS}{BS}~{DOWN}"

Name it macro.vbs

When I instantiate the WshShell object I need to be able to refer to it in some way. Wsh is a variable for this purpose so, first of all, I explicitly declare it with the Dim statement

Set Wsh = Wscript.CreateObject("Wscript.Shell")

This is where I make an instance of the WshShell object.

Note that, as I am using the CreateObject method of WScript, I use the dot notation Wscript.CreateObject to call the method. The bit in brackets is what is called the 'programmatic identifier' of the object to be created and its value is in the documentation! The created object is then assigned to wsh so I can refer to it.

Wsh.AppActivate "Exploring"

Having set everything up this is the first line of real coding. It uses the AppActivate method of the newly defined WshShell object to tell the computer which window is to be activated for subsequent operations. (Which window is given focus is the techie way of saying this!). The string value, "Exploring" in this example, says activate the windows whose title begins with 'Exploring'. On my version of Windows at least, that means a Windows Explorer window. Note that if two Windows Explorer windows were open this code may activate the wrong one. I have not found this to be a problem in the way I use the code as a keyboard macro, since the Explorer window I wish to use has focus already.

Wsh.SendKeys "{F2}{END}{LEFT}{LEFT}{LEFT}{LEFT}{BS}{BS}{BS}~{DOWN}"

This uses the SendKeys method of the created WshShell object to send the keys to the Explorer window. The bits in quotes are the keys to send. Standard alphanumeric keys are simply typed as is. Special code strings, usually in braces, are used to define function keys. The keys in the line above correspond with the keyboard process defined in the previous section. Here is a full list of code strings taken from the documentation for SendKeys. Note that there does NOT appear to be a way of sending the special keys on a Windows keyboard

keyboard.

Key
 Code String
 
BACKSPACE
 {BACKSPACE}, {BS}, or {BKSP}
 
BREAK
 {BREAK}
 
CAPS LOCK
 {CAPSLOCK}
 
DEL or DELETE
 {DELETE} or {DEL}
 
DOWN ARROW
 {DOWN}
 
END
 {END}
 
ENTER
 {ENTER} or ~
 
ESC
 {ESC}
 
HELP
 {HELP}
 
HOME
 {HOME}
 
INS or INSERT
 {INSERT} or {INS}
 
LEFT ARROW
 {LEFT}
 
NUM LOCK
 {NUMLOCK}
 
PAGE DOWN
 {PGDN}
 
PAGE UP
 {PGUP}
 
PRINT SCREEN
 {PRTSC}
 
RIGHT ARROW
 {RIGHT}
 
SCROLL LOCK
 {SCROLLLOCK}
 
TAB
 {TAB}
 
UP ARROW
 {UP}
 
F1
 {F1}
 
F2
 {F2}
 
F3
 {F3}
 
F4
 {F4}
 
F5
 {F5}
 
F6
 {F6}
 
F7
 {F7}
 
F8
 {F8}
 
F9
 {F9}
 
F10
 {F10}
 
F11
 {F11}
 
F12
 {F12}
 
F13
 {F13}
 
F14
 {F14}
 
F15
 {F15}
 
F16
 {F16}
 

The documentation also tells you how to send the Ctrl and Alt keys in combination with alphanumeric keys.

Having created the script with Notepad, or whatever, save it to a VBScript file, (a file which has a .vbs extension). For the purpose of this example I will assume it is saved to:

C:\My Documents\WindowsScripts\Remove(n).vbs

CONVERTING THE SCRIPT TO A KEYBOARD MACRO
You could run this script in the same way as the Hello.vbs script was run, but it would be pointless. If you double clicked the Remove(n).vbs file then it would be the file highlighted and the effect of the script would be to rename the file to Remove.vbs.

We need to highlight a file of choice to be renamed and then execute the script. The way to do this is to assign a key combination to run the script. For example, if we set things up so that the key combination Ctrl-Alt-z ran the script then we could highlight the file whose name is to be changed and then press Ctrl-Alt-z. As the script will, after execution, highlight the next file in the Explorer window we could amend the names of a group of adjacent files simply by pressing Ctrl-Alt-z as many times as necessary. Even if the odd file in the window does not need its name amending we could press cursor down instead of Ctrl-Alt-z and then carry on.


Windows provides a means of assigning a key combination to run a file. You have to create a shortcut to the file ON THE DESKTOP. Creating a shortcut is not sufficient. It has to be on the desktop! Create a shortcut anywhere else and the key combination does not work. Whoever dreamt up this restriction of Windows functionality was obviously on the sauce on the day in question! Nevertheless, it does mean I have finally found a use for the desktop. I never start a program by clicking a desktop icon. I'm a clean desktop man and do not like it overrun with icons!

In the example we want to create a shortcut to C:\My Documents\WindowsScripts\Remove(n).vbs on the desktop. Do this as follows:

Right click the desktop and select New and Shortcut from the context menu. 
Click the Browse button 
Navigate to the C:\My Documents\WindowsScripts directory 
Click the down arrow next to the 'Files of type' box and select All files 
In the list of files displayed select Remove(n).vbs and click the Open button 
Click the Next button 
Give the shortcut a name, say Remove(n), and click the Finish button. 
A shortcut with the name Remove(n) will appear on the desktop. Right click it and select Properties from the context menu. 
Put the cursor in the Shortcut key box by clicking the box 
Press Ctrl-Alt-z together 
Click the OK button. 
That is all there is to it. Any time you need the script to execute just press Ctrl-Alt-z.

CREATING OTHER KEYBOARD MACROS

Now that I have explained how to create this example keyboard macro you have the template to create others. You have two things to change in the script:

Replace the "Exploring" in the Wsh.AppActivate line with the start of the title of the windows in which the macro is to work.

Define the keys to send in the Wsh.SendKeys line.

Save the revised script as another file and create another shortcut on the desktop with a different key combination.

If you are only going to use the keyboard macros infrequently you may wish to create the desktop shortcut only at the time of use and always use the Ctrl-Alt-z combination for its Shortkey. It saves remembering lots of different combinations or choosing a combination which conflicts with a shortcut in the application being used.

CONCLUSION

I hope this discussion has opened your eyes as to the possibilities of Windows Scripting Host. I have already written my second script. I mentioned in the Blog at the beginning of the year a problem I was having at work, which I solved by an inelegant method of opening Explorer using Dynamic Data Exchange. It worked but, ever searching for the elegant method, I finally worked out a solution using a script, which did not use DDE at all. That script is now a fixture on my Office Shortcut Bar and my problem has gone away.

I am thinking of returning to another problem that has been with me since the beginning of Windows 9x. How to open 2 instances of Windows Explorer and tile them horizontally over the full screen. In this way I can drag and drop copy like was done with the old File Manager. At present I create this interface manually, when I need it. How much easier it would be if I could write a script to do the creation for me.

Update
Here is the script for dual Explorer windows:

'A script to open Dual Windows Explorers on folders of the user's choice.
'
'The script should be called with TWO parameter which define the folders to open
'
Dim sa
Set sa = Wscript.CreateObject ("Shell.Application")
If WScript.Arguments.Count = 2 Then
sa.explore WScript.Arguments.Item(0)
sa.explore WScript.Arguments.Item(1)
Else
WScript.Echo "Please call this script with TWO argument to define the folders to open"
End If
Wscript.sleep(1)
sa.TileHorizontally()


Maybe you have some problems that can be solved with a script. Now that you know about WSH, take a look at it and see if you can solve those problems and discover the joy of being in control of Windows.

If you create some useful scripts please send them to me for upload. They can then be shared with the whole ICPUG community.

READER WRITES

Cesar writes to say:

I just read your web page where you describe the use Windows scripting. I’m having looking for several days this type of solution. I was wondering if you could give me a tip. I need to create a simple script that basically executes the {scroll} + {scroll} combination, as simple as that. Is this something I can do with Windows scripting. I appreciate your page, it is going to be very useful for certain issues I need to solve.
I see no problems with sending what Cesar wants. The Help file for Windows Scripting 5.6 says the keys are: 

{SCROLLLOCK}{+}{SCROLLLOCK} 

(Note: There are 3 'L's in SCROLLLOCK!)

UPDATE: 25 APRIL 2004

One of the keys that the SENDKEYS method of WSH will not emulate is the Windows key (beside the ALT keys on a Windows keyboard). Also, it is not possible to define the Windows key as the keyboard trigger for a desktop shortcut.

Mike Newman writes to tell me of a program, Winkey, that will allow you to write Windows-key keyboard shortcuts. It is a free download at:

http://download.com.com/3000-2344-913626.html?tag=lst-0-1

Another problem with WSH is that it cannot emulate the numeric keypad keys. This makes it impossible to create, for example, the character defined by pressing the ALT key in combination with the numeric keypad keys 0230. Microsoft Word has an alternative shortcut to this character, press CTRL-& followed by a, but this will not apply to all applications. Why would generation of this character be useful? Apparently, Esperanto writers use this and other symbols to write certain Esperanto characters that are not available in English. If anyone has a solution to this puzzle let me know.

Friday, May 28, 2010

Selenium Testing articles

1) http://blogs.atlassian.com/developer/2009/06/selenium_testing_with_windows.html

2) http://www.thoughtworks-studios.com/twist-agile-test-automation/1.0/help/how_do_i_use_selenium_to_test_https_sites.html

3) http://yuce.tekol.net/2009/10/web-application-testing-with-selenium.html

Wednesday, May 26, 2010

Application Status Checking with WLST

def appStatus(server_name):
       try:
           print '---------------------- Application status---------------------'
           mBeans=adminHome.getMBeansByType("ApplicationRuntime")
           for bean in mBeans:
               if server_name != bean.getObjectName().getLocation():
                   continue
               components= bean.lookupComponents()
               for componentRTList in components:
                   #ejbRTList=componentRTList.getMBeansByType("EJBComponentRuntime")
                   app = componentRTList.getParent().getName()
                   istate=componentRTList.getDeploymentState()
                   if istate == 0:
                       istate='UNPREPARED'
                   if istate == 1:
                       istate='PREPARED'
                   if istate == 2:
                       istate='ACTIVE'
                   if istate == 3:
                       istate='NEW'

                   print "%65s %65s %7s" % (str(componentRTList.getName()), app, istate)

       except:
           print "This Server has no Applications"

Saturday, May 08, 2010

Perl: Reading Processes from Unix

Here is a way using pipes

open(PS_F, "ps -f|");

while () {
($uid,$pid,$ppid,$restOfLine) = split;
# do whatever I want with the variables here ...
}

close(PS_F);

You can also try with split(/\s+/,$_)

Good Presentation on Patterns

http://www.cs.clemson.edu/~malloy/courses/patterns/slides/

Friday, May 07, 2010

Perl and Unix Processes control

Here is a script fot this

http://aplawrence.com/Unix/perlforkexec.html

http://docstore.mik.ua/orelly/perl/cookbook/index.htm