-3

I need the script to run at specific times, gets the system time to determine which url to open, takes the screenshot, saves it and send it via mail. If i break the code down portions of it run but when i include the time checks and if statement it doesn't run. Here is the script i came up with but its not running.

Function Get-shot { 
    $now = (Get-Date -Format "hh:mm:ss") 
    $ie=new-object -com "InternetExplorer.Application" 
    $ie.Visible=$true 
    $path="C:\checks"

    Function takeshot {
        $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
        $ScreenshotObject = New-Object Drawing.Bitmap 
        $ScreenBounds.Width, 
        $ScreenBounds.Height
        $DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject)
        $DrawingGraphics.CopyFromScreen($ScreenBounds.Location, [Drawing.Point]::Empty, $ScreenBounds.Size)
        $DrawingGraphics.Dispose()
        $ScreenshotObject.Save($FilePath)
        $ScreenshotObject.Dispose()
    }

    Try {

        Add-Type -Assembly System.Windows.Forms

        If ($now -eq "08:28:00")
        {
            <#opens internet explorer and navigates to the page#>
            $ie.navigate("www.google.com")
            $Time = (Get-Date)
            [string] $FileName = "$($Time.Month)"
            $FileName += '-'
            $FileName += "$($Time.Day)" 
            $FileName += '-'
            $FileName += "$($Time.Year)"
            $FileName += '-'
            $FileName += '.png'
            [string] $FilePath = (Join-Path $Path $FileName)

            #takes the screenshot
            DO {

                takeshot

                Write-Verbose "Saved screenshot to $FilePath." 

            } while ($now -eq "08:28:30")

        }    

    } Catch {
        Write-Warning "$Error[0].ToString() + 
        $Error[0].InvocationInfo.PositionMessage"
    }
}
Frode F.
  • 46,607
  • 8
  • 80
  • 103
  • 1
    it seems you did not paste all your code – Gilles Gouaillardet Mar 03 '18 at 12:07
  • You're using nested function declarations. Do you do this with a purpose? What purpose? – Olaf Mar 03 '18 at 20:16
  • Possible duplicate of [Focus IE window in powershell](https://stackoverflow.com/questions/27282919/focus-ie-window-in-powershell) – JosefZ Mar 03 '18 at 22:05
  • @GillesGouaillardet yes i wanted to fix the screenshot code first before adding the send-mailmessage function. – athanas otieno Mar 04 '18 at 12:46
  • @Olaf Maybe i wasn't clear enough on what exactly i needed, I have 4 different urls that i need the code to open at different times of the day and take the screenshot, hence the choice of nested function. – athanas otieno Mar 04 '18 at 12:50
  • No. I didn't mean nested functions I meant nested function declarations. Everytime you run the "outside" function you declare the inside function again. That's at least unnecessary if not error prone and hard to maintain. – Olaf Mar 04 '18 at 14:01

1 Answers1

0

You don't state where this will be run. Meaning:

  1. On a server / workstation you control, and are interactively logged on to.
  2. On a server / workstation you control and you are not interactively logged on to.
  3. On a server / workstation you control, that someone else is logged on to.
  4. You don't say if this is to be a scheduled task or an event monitor.
  5. You don't say or show how the target URL is determined. So, is it embedded, pulled from some list, or user input.
  6. You are calling the bitmap type but specifying .png extension.
  7. You don't handle multi-monitor in your code.

There are several things that are not correct in your posted code.

  1. File paths do not match up. You have $path is some place
  2. The nested function declaration is not really needed based on what you are after.
  3. The way you are calling the object for the bitmap is not correct, as it will generate errors, which you don't show in your code.

WARNING: A constructor was not found. Cannot find an appropriate constructor for type Drawing.Bitmap. A constructor was not found. Cannot find an appropriate constructor for type Drawing.Bitmap. You cannot call a method on a null-valued expression. You cannot call a method on a null-valued expression. Exception calling "FromImage" with "1" argument(s): "Value cannot be null.

  1. I am not sure why the need for the Do/While, since you need only to call the take shot code once.
  2. Your code will not start at any predetermined time, unless you have a scheduled task or some other event trigger to start it.

An for this...

but when i include the time checks and if statement it doesn't run.

Your code assigns a definitive time.

If ($now -eq "08:28:00")

If it is not that exact time, when you run the code, the code will not run, because you told it not to, if it is not 08:28:00".

If you are running this throughout the day for your testing. Change the above to this...

If ($now -ge "08:28:00")

Yet, again, this does not really make since. As I stated earlier, unless this code is on some type of trigger, WMI event, Scheduled Task, already running in memory via a infinite loop (not a good thing BTW, well, you could set a timed cycled one), then it is not going to fire anyway.

Walkthrough (you'll have to wrap your logic around this example - including any multi-monitor stuff)

Clear-Host
$StartTime = $null
$TargetUrl = $null
$FileName = $null
$File = $null
# script to run at specific times
## Set up a schedueld task for the script run cycle(s)
### Scheduled Task (set script run daily at "08:28:00") )
### WMI Event Monitor (check for clock time of "08:28:00"))
### Load the script on boot up and use a timed infinite loop (Load at boot, Loop un time time of "08:28:00" - need to reload script each day to handle if use never reboots)


# determine which url to open
# How the URL is determined
$TargetUrl = "google.com"
# Get-Content -Path "D:\Temp\UrlList.txt" | Get-Random -Count 1 
# $ResponseUrl = (Read-Host -Prompt "Enter the URL to use")

# Open the IE to the needed URL
$ie = new-object -com "InternetExplorer.Application"
$ie.navigate($TargetUrl)
$ie.visible = $true
$ie.fullscreen = $False

While ($ie.Busy) {Start-Sleep -Milliseconds 100}

# take the screenshot and saves it

Function New-ScreenShot
{
    [CmdletBinding()]

    [Alias('nss')]

    Param
    (
        # [Parameter(Mandatory = $true)]
        [string]$Path = "$env:USERPROFILE\Pictures"
    )

    $FileName = "$($env:COMPUTERNAME)_$(get-date -f yyyyMMddHHmmss).bmp"
    $File = "$Path\$FileName"

    Add-Type -AssemblyName System.Windows.Forms
    Add-type -AssemblyName System.Drawing

    # Gather Screen resolution information
    $Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen
    $Width = $Screen.Width
    $Height = $Screen.Height
    $Left = $Screen.Left
    $Top = $Screen.Top

    # Create bitmap using the top-left and bottom-right bounds
    $bitmap = New-Object System.Drawing.Bitmap $Width, $Height

    # Create Graphics object
    $graphic = [System.Drawing.Graphics]::FromImage($bitmap)

    # Capture screen
    $graphic.CopyFromScreen($Left, $Top, 0, 0, $bitmap.Size)

    # Save to file
    $bitmap.Save($File) 

    Write-Output "Screenshot saved to:"
    Write-Output $File
    Start-Sleep -Seconds 1
    Start-Process -FilePath mspaint -ArgumentList $File
}

New-ScreenShot

# send it via mail
# from the PoSH built-in help file
# Example 2: Send an attachment

Send-MailMessage -From "User01 <user01@example.com>" `
-To "User02 <user02@example.com>", "User03 <user03@example.com>" `
-Subject "Sending the URL Screenshot Attachment" `
-Body "Forgot to send the attachment. Sending now." `
-Attachments $File -Priority Low -dno onSuccess, onFailure -SmtpServer "smtp.example.com"

Update Relative to the the OP comments

– athanas otieno

Sure you can do different types. What I provided was the basics to do this. There are far more elegant options. There are plenty of other samples to be leveraged that show .png or .jpg use case. These are all over the web and even on this very site. See these posts.

How can I do a screen capture in Windows PowerShell?

Get-Screenshot.ps1

<# 
 .Synopsis 
     Gets a screen capture 
 .Description 
     Captures the current screen 
 .Example 
     # Capture the whole screen 
     Get-ScreenShot 
 .Example 
     # Capture the current window 
     Get-ScreenShot -OfWindow 
 .Example 
     # Capture a set of coordinates 
     Get-ScreenShot -OfCoordinates 320, 240 
 .Link 
     http://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell

 #>

# The image format used to store the screen capture
[Parameter(ValueFromPipelineByPropertyName=$true)]
[ValidateSet('PNG', 'JPEG', 'TIFF', 'GIF', 'BMP')]
[string]
$ImageFormat = 'JPEG', https://www.powershellgallery.com/packages/RoughDraft/0.1/Content/Get-Screenshot.ps1

Take-Screenshot This script has a function that allows you to take a screenshot of the entire desktop or of an active window. Also includes option to save the screenshot to a file.

Take-ScreenShot -screen -file "C:\image.png" -imagetype png

https://gallery.technet.microsoft.com/scriptcenter/eeff544a-f690-4f6b-a586-11eea6fc5eb8/view/Discussions

Even this script appears to be where you got yours from, but I could be wrong, as often it's really easy to see folks to end up similar things. It has happen to me many times. Of course forking / borrowing and tweaking is a thing.

Changing a screenshot to JPG instead of PNG

I've got a script that works that runs on a scheduled task to snapshot the screen of a computer. Basically the computer runs a query at a regular interval that is pretty resource intensive on the server but has information that anyone might want to see at a given time.

https://social.technet.microsoft.com/Forums/windowsserver/en-US/c121b827-44c8-49ac-83c6-356fa720e169/changing-a-screenshot-to-jpg-instead-of-png?forum=winserverpowershell

postanote
  • 11,533
  • 2
  • 7
  • 16
  • thank you for the above, just to be clear, the script will be a scheduled task to run at 5:00 am, 5:15 am, 9:00 am and 9:15 am, with a delay of 30 seconds to allow the browser to load the site; each of the above times a different url will be opened to take the screenshot. I intend to run it on a remote computer that i have access to. I need the image in png or jpeg format. – athanas otieno Mar 04 '18 at 13:04
  • Sure you can do different types. What I provided was the basics to do this. There are plenty of other samples to be leveraged that show .png or .jpg use case. These are all over the web and even on this very site. See the update I added for you. – postanote Mar 04 '18 at 23:42