Spooniom all my code is belong to you project

PowerShell: RoboClicky V2 Mouse Move, Click, Screen Capture

This script does a few things.  I will break it apart into separate posts that deal with each bit, but for now here is the whole lot.

The purpose of this script is to;

  • move the mouse to specific screen coordinates
  • click mouse buttons at those coordinates in order to drive an application
  • give the application time to respond
  • take a screenshot
  • save the screenshot as required
  • cater for multiple screens in a horizontal configuration

There are some functions in this one not specifically related to the objectives, but for reasons I won’t go into here, I generally try to keep all scripts as self-contained as possible.  I will try to break this out when I get time.

#region Includes
# ======================  Add some required bits and import some DLLs

     # System drawing and windows forms

        [Reflection.Assembly]::LoadWithPartialName("System.Drawing")
        [Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
 
     # Some mousey things

        $signature=@' 
            [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
             public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'@ 

        $SendMouseClick = Add-Type -memberDefinition $signature -name "Win32MouseEventNew" -namespace Win32Functions -passThru 
     
     # Stopwatch for timing the whole process 
    
        $SWScriptTime = [Diagnostics.Stopwatch]::StartNew()

#endregion Includes


#region Variables
    # ====================== Define Some Screen Variables

        # Screen size related variables 

            $baseScreenSizeX = 1920 #pixles
            $baseScreenSizeY = 1080 #pixles
            $sleepPeriod = 20 #seconds 
            $baseimagepath = "D:\RoboClicky\images\"
    
        # Log File Variables    
    
	        $appVersion = "RoboClicky Version 2"
            $logMonth = (Get-Date -Format "yyyy-MM-")
	        $logDay = (Get-Date -Format "dd-")
            $basePath = ""
            $logFile = ""
            $logDestinationDetail = $basepath + "D:\RoboClicky\"+$logmonth+$logday+"RoboClicky_Detail_Log.txt"   


        # Temporary session log

            $global:currentLog = ""

#endregion Variables

#region FUNCTIONS
    
    # ====================== FUNCTIONS

        #region GenericFunctions 
    
        # I use these in many of my scripts

            # ====================== Format Date Function

                   function GetDateFormatted(){
                        Return (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
                        }
      
                   function GetDateFormattedForPaths(){
                        Return (Get-Date -Format "yyyy-MM-dd HHmmss")
                        }

            # ====================== Logging Function

                    function LogThis($logthisstring){
                                $logEntry = (GetDateFormatted)  + "# " + $logthisstring
                                $global:currentLog = $global:currentLog + "`n" + $logentry
                                $logEntry | Out-File $logDestinationDetail -Append
                                $logEntry | Out-host
                    }

            # ====================== Path Testing Function 
              function CheckFileExists($checkPath){
                $filexists = (test-path ($checkPath))
                logthis("Check Path: " + $checkPath + " | file exists = " + $filexists)
                return $filexists
              }

            # ====================== Exit Block

            $ExitNow = {
                # find me a line Morpheus 
                     $SWScriptTime.Stop()
                     logthis("EXIT NOW! Script complete in " + $SWScriptTime.Elapsed + " ... welcome to the real world Neo ...")
                    $global:currentLog | Out-File $currentLogPath -Force
                         exit
                    }

        #endregion GenericFunctions 

#region RoboClickyFunctions

    # ====================== Return mouse to 0,0 coordinates

    function mooseHome(){
        logthis ("F: moving mouse now to coordinates: 0,0")
        [Windows.Forms.Cursor]::Position = "0,0"
        return 

    }

    # ====================== Move mouse to specified coordinates and sleep for sleep period

    function mooseMove($screenNumber, $xCoords, $yCoords, $label, [boolean]$isrelative, $loadWaitPeriod){

    
        # NOTE::: This code only handles displays that have left to right numbering.  Future upgrade will include full relative screen handling.  Because it would be awesome!

            #Log some things 
            
                logthis ("F: mooseMove function called with paramaters;")
                logthis ("     screenNumber = "+$screenNumber)
                logthis ("     xCoords = "+$xCoords)
                logthis ("     yCoords = " +$yCoords)
                logthis ("     label = " + $label)
                logthis ("     isrelative = " + $isrelative)
                logthis ("F: calculating absolute coordinates")

            #Set Absolute X coordinates of the screen (which are relative to the entire screen canvas)
            
            $absolutexCoords = $xCoords + ($baseScreenSizeX * $screenNumber)
            $absoluteyCoords = $yCoords

            $coords = "$($absolutexCoords),$($absoluteyCoords)"
    
                logthis ("      ... "+$coords)    
                logthis ("F: moving mouse now to screen " + $screenNumber + ", relative coordinates: x=" + $xCoords + ", y=" + $yCoords + ", absolute coordinates: "+$coords)

                # move the mouse 
                [Windows.Forms.Cursor]::Position = $coords
    
                # perform left mouse click using mooseClick function
                mooseClick

            logthis ("F: sleeping for: " + $sleepPeriod +" seconds to allow for screen rendering")
    
            sleep $loadWaitPeriod

            mooseHome

            return 
    }


    # ====================== Perform left mouse click

    function mooseClick
    {
        logthis ("F: left mouse clicking now")
            $SendMouseClick::mouse_event(0x00000002, 0, 0, 0, 0); #Left Mouse Down
            $SendMouseClick::mouse_event(0x00000004, 0, 0, 0, 0); #Left Mouse Up
        return
    }

    # ====================== Grab ScreenShot of screen X


    function screenshot($displaynumber,$screenshotname) {
   
       logthis ("F: Performing screen capture of display "+$displaynumber)

            #$bounds = [Drawing.Rectangle]::FromLTRB($screen.Left, $screen.Top, $screen.right, $screen.bottom)
            #$bounds = [Drawing.Rectangle]::FromLTRB(-236, -1080, 1684, 0)

            #calculating cooridinates for screen capture
                logthis("#calculating cooridinates for screen capture")

                $captureLeft = $baseScreenSizeX * $displaynumber
                $captureTop = 0 # fixed value in this version
                $captureRight = ($baseScreenSizeX * $displaynumber) + 1920
                $captureBottom = 1080 # fixed value in this version

                $bounds = [Drawing.Rectangle]::FromLTRB($captureLeft, $captureTop, $captureRight, $captureBottom)

                $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height

                $graphics = [Drawing.Graphics]::FromImage($bmp)


                logthis("F: Screen capturing from absolute range:")
                logthis("     Left: "+$captureLeft)
                logthis("     Top: "+$captureTop)
                logthis("     Right: "+$captureRight)
                logthis("     Bottom: "+$captureBottom)

                # create image 

                   $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
                   $path=$baseimagepath + $screenshotname + ".png"
                   logthis ("F: Saving screen capture as "+$path)
                   $bmp.Save($path)
                   $graphics.Dispose()
                   $bmp.Dispose()

    }



    function refreshIE($refreshStringRef)
    {

    # Function to refresh IE window with a specific name
        logthis("F: Refreshing IE Where name of window contains '" + $refreshStringRef +"'")
        $shell = new-object -ComObject shell.application
        $shell.windows() | 
                Where-Object { $_.document.url -like $('*' + $refreshStringRef + '*')} | 
                ForEach-Object { $_.refresh() }

    }

#endregion RoboClickyFunctions

#endregion FUNCTIONS


#region Mainline

    # Step 1 - Refresh IE window containing application visualisation

        refreshie -refreshStringRef "ie-application-window-name"
        logthis ("waiting for ie-application-window-name")
        sleep 30

    # Step 2 - Move mouse around the visualisation using the mooseMove function, then snap an image of it using the screenshot function. 
    
        # Zone A

        mooseMove -screenNumber 6 -xCoords 685 -yCoords 21 -label "Zone A" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_A"

        # Zone B

        mooseMove -screenNumber 6 -xCoords 797 -yCoords 21 -label "Zone B" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_B"


        # Zone C

        mooseMove -screenNumber 6 -xCoords 908 -yCoords 21 -label "Zone C" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_C"

        # Zone D

        mooseMove -screenNumber 6 -xCoords 1020 -yCoords 21 -label "Zone D" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_D"

        # Zone E

        mooseMove -screenNumber 6 -xCoords 1131 -yCoords 21 -label "Zone E" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_E"

        # Zone F

        mooseMove -screenNumber 6 -xCoords 1242 -yCoords 21 -label "Zone F" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_F"

        # Zone G

        mooseMove -screenNumber 6 -xCoords 1354 -yCoords 21 -label "Zone G" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_G"

        # Zone H

        mooseMove -screenNumber 6 -xCoords 1465 -yCoords 21 -label "Zone H" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_A"


        # Zone etc...

        mooseMove -screenNumber 6 -xCoords 1576 -yCoords 21 -label "Zone etc... and so on" -isrelative $true -loadWaitPeriod 25
        screenshot -displaynumber 6 -screenshotname "Dashboard_Zone_Summary"

&$exitnow

#endregion Mainline