PowerShell: Start all VMWare services, self elevate to admin

For reasons, all my VMWare services are set to manual startup.  I like it this way.

I wanted an easy way to start all the services so naturally, a PowerShell script was required.  However the services can’t be started by PowerShell without elevated privileges, and I usually work in a non-elevated ISE.  So this version of the script self-elevates, saving me precious seconds.

# Start All VMware services V2
# WARNING - THIS SCRIPT WILL ATTEMPT TO ELEVATE ITSELF

# Check if the current user role is in the local computer administrator role

            # get-service -displayname 'VMware*' | %{Stop-Service -name $_.Name}

If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
    [Security.Principal.WindowsBuiltInRole] "Administrator")){
               
               # Not running as administrator

                # Create a new process object that starts PowerShell
                   $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
   
                   # Specify the current script path and name as a parameter
                   $script:MyInvocation.MyCommand.Path
                   $newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
   
                   # Indicate that the process should be elevated
                   $newProcess.Verb = "runas";
   
                   # Start the new process
                   [System.Diagnostics.Process]::Start($newProcess);
   
            }
               
        Else
        {     
 
        # Elevated Code - will only run if IS Administrator 
            
            # Set some colors so its clear what is going on
            
                $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
                $Host.UI.RawUI.BackgroundColor = "DarkRed"
                clear-host

            # start all the VMware services
            
                $s = get-service -displayname 'VMware*' # i should really list the services in the right startup order
                write-host $s

                    foreach ($svc in $s){

                        write-host $svc.name 'is' $svc.Status
                      
                        if($svc.Status -ne "Running")
                        {
                            write-host 'Starting: ' $svc.Name
                                #Stop-Service $svc.name
                                #set-service $svc.Name -StartupType Manual
                            Start-Service $svc.Name

                        }
                        Else{
                             # Do something else if you want
                        }
                    }


                #start "C:\Program Files (x86)\VMware\VMware Workstation\vmware.exe"      
                    }

 # Re-present the services again

     get-service -displayname 'VMware*'
     
        Write-Host "Sleeping 60" 
        start-sleep -seconds 60

 

 

 

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

 

 

 

 

 

 

 

 

Open Sourcing – all my code is belong to you!

Version 0.1

<# 
SYNOPSIS: In the spirit of sharing that enabled me to learn how to code, I am now open sourcing all of my code, that it may be of some use to others.  Enjoy!

TO DO: I'd like to get around to describing all of the problems each solution solved for, but for now its just a minimalist dump.
 
#>

 

I first learned to code in ZX Spectrum BASIC at around the age of 10.  It was 1986.  More accurately, I learned to type and eventually understand the code from various ‘program your own games’ books and ‘Sinclair User’ magazine articles.

It was a little later that I actually achieved an understanding of the primitive building blocks of the code.

Quite possibly my young brain was prepped for the logic and structure of programming through my obsession with the essentially ‘if-then-else’ based Fighting Fantasy series of ‘choose your own adventure’ game books.

‘The Warlock of Firetop Mountain’ was the first I remember owning, and I believe the first in the series. They were awesome.  My very early unguided ventures into coding my own programs were literally codifications of these simple narratives.

I, like many people, have learned a lot of what I know about coding from commercially driven ‘pay for knowledge’ sources such as at university, training courses, and books. However, I am just old enough to claim some memory of the relatively early years of open source code sharing.

So, like everybody, I have also learned a stack from the open source information made available by the generosity, or naivety, nevertheless sheer enjoyment of sharing through magazines, blogs,  websites, friends and various other mediums.

So, I have decided to dig up and throw into the pot of shared online code, a bunch of my own work; better or poorer to be debated, but certainly useful.

Note: I don’t claim that any of this code still works, nor either that that which does, is optimal for the task.  Much of it is old, some of it is new, the context and constraints of the environment it was written for are here absent, but it all served a purpose.