≡ Menu

Powershell: Script to take a screenshot of your desktop

“Could you please send me a screenshot of what you are seeing?”. This is a frequent question we system administrators ask the end users. So, I just got a thought why I can’t take a screenshot of desktop using powershell so that I can incorporate this to my other automations if needed. That is when this script born.

When searched in google for this, I found a stackoverflow thread(http://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell) where different approaches are described to take a screenshot using powershell. I could make only one method working and the other is having problems. However, the working method has a limitation as I need to explicitly pass the width and height of the screen that has to be captured. If I am interested on whole screen, from where I can get these coordinates? My previous post(Get-ScreenResolution) came handy here. I read the screen resolution details using Get-Screenresolution.ps1 script and passed the output to the function I found in stackoverflow. Now it is working exactly the way I want.

For general usage, I made few more modifications to the code to allow explicitly pass the width and height details using -Width and -Height parameters. There is also another parameter called -FileName using which you can provide the name you want for the screenshot. Don’t provide a file extension here. The script saves the output in PNG format by default. If -FileName parameter is not specified you can see the output in %temp% with Screenshot.png name.

Get-ScreenShot.ps1

[cmdletbinding()]
param(
  [string]$Width,
  [string]$Height,
  [String]$FileName = "Screenshot"

)

#Function to take screenshot. This function takes the width and height of the screen that has
#to be captured

function Take-Screenshot{
[cmdletbinding()]
param(
 [Drawing.Rectangle]$bounds, 
 [string]$path
) 
   $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
   $graphics = [Drawing.Graphics]::FromImage($bmp)
   $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
   $bmp.Save($path)
   $graphics.Dispose()
   $bmp.Dispose()
}

#Function to get the primary monitor resolution.
#This code is sourced from 
# https://techibee.com/powershell/powershell-script-to-get-desktop-screen-resolution/1615

function Get-ScreenResolution {
 $Screens = [system.windows.forms.screen]::AllScreens
 foreach ($Screen in $Screens) {
  $DeviceName = $Screen.DeviceName
  $Width  = $Screen.Bounds.Width
  $Height  = $Screen.Bounds.Height
  $IsPrimary = $Screen.Primary
  $OutputObj = New-Object -TypeName PSobject
  $OutputObj | Add-Member -MemberType NoteProperty -Name DeviceName -Value $DeviceName
  $OutputObj | Add-Member -MemberType NoteProperty -Name Width -Value $Width
  $OutputObj | Add-Member -MemberType NoteProperty -Name Height -Value $Height
  $OutputObj | Add-Member -MemberType NoteProperty -Name IsPrimaryMonitor -Value $IsPrimary
  $OutputObj
 }
}

#Main script begins

#By default captured screenshot will be saved in %temp% folder
#You can override it here if you want
$datetime = (Get-Date).tostring("dd-MM-yyyy-hh-mm-ss")
$FileName = "{0}-{1}" -f $FileName, $datetime
$Filepath = join-path $env:temp $FileName

[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [Reflection.Assembly]::LoadWithPartialName("System.Drawing")

if(!($width -and $height)) {

 $screen = Get-ScreenResolution | ? {$_.IsPrimaryMonitor -eq $true}
 $Width = $screen.Width
 $Height = $screen.height
}

$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, $Screen.Width, $Screen.Height)

Take-Screenshot -Bounds $bounds -Path "$Filepath.png"
#Now you have the screenshot

Usage:

Simple, just run the script from powershell window, you will see the output in %temp%\screenshot-29-02-2020-07-34-04.png

Hope this helps… feedback welcome.

Comments on this entry are closed.

  • sowmiya August 5, 2014, 4:28 pm

    Hi,
    Can yu plz help me as how to take screen shot of the entire aspx webpage?

  • Shivakumar June 5, 2017, 11:06 pm

    Hi, Greetings!!
    I need script for below requirement. I have searched it in many websites but couldn’t find it.
    I have tried your script it is working fine but I don’t know how to use that script for my requirement. Thanks!!

    Could you please help on below.
    1) I need to copy name(www.abcd.com) in browser and press enter
    2) Take screen shot for only specified area
    3) Repeat this for different names servers

    • Wintel Rocks June 27, 2017, 2:11 pm

      Hi ShivaKumar,

      Unfortunately we cannot take new requirements and deliver the scripts. No such professional services available with us. However, looking at your requirement, it is very simple and there are some scripts out there to help you.

  • PD Subraa August 12, 2017, 4:49 pm

    Can you please guide me how to execute this process for every interval – say 5 minutes?

    Thanks!!

    • Wintel Rocks August 13, 2017, 9:53 am

      Hi,

      you may try scheduling this script as a scheduled task under current logged on user.

      • Agnish Chakraborty February 17, 2020, 3:12 pm

        First! thank you for this and all your efforts. Now the issue I’m facing. I can’t schedule this script as it is overwriting the previously captured file. please guide me how to make the files saved in a chronological order.

        • Wintel Rocks February 29, 2020, 5:09 pm

          Updated the script to generate PNG file with date and time appended in the name. Try the latest code from the post.

  • Subbu August 14, 2017, 12:26 pm

    It has helped me in the right time. Next challenge is e-mail them to admin every 2 hours [zipping the screen shots]

    Is there any solution you have at your end?

  • graham September 28, 2017, 3:09 pm

    This looks great.
    I use an App which doesn’t provide useful file thumbnails. So I want to put a screenshot of each file with the same name ( but with .PNG extension) in the same folder. I’d like to do this for a whole folder.
    Can you point me to a script which can help to
    1 Open each file in a folder (Optionally recursive sub-folders)
    2 Grab the filename
    3 Do a screenshot (your script)
    4 Save the screenshot with the same filename but with the .PNG extension to the folder the file was opened from.
    5 Close the file
    6 Until all the files in the folder(s) are done.
    ??
    Aren’t there here scripts for recursive file handling somewhere out there?
    Thanks for your help.

    • Wintel Rocks September 28, 2017, 9:12 pm

      Getting files recursively is easy using below. However, for your requirement, a custom script needs to be developed.

      Get-ChildItem -Recurse

  • graham September 28, 2017, 3:12 pm

    PS: I have a whole 20 years backlog of these files (possibly many thousands) and I’m now trying to find the important ones.

  • Raviteja J October 10, 2019, 9:54 am

    Hi TechiBee,

    Thanks for the script its works fine when we run on local desktop powershell but it prints blank image when we try to run on remote desktop using ansible.

    Can you please suggest how to take screenshot on remote desktop.

    Thanks
    Raviteja

    • Wintel Rocks October 12, 2019, 3:47 pm

      I believe it is not that easy. You may try scheduling the PowerShell script on the remote machine to run under logged-on user credentials and see if that helps.

  • John November 13, 2019, 8:26 pm

    Ok, so it kind of worked. I have an app running on my pc and I want to take a screenshot of it. But apparently it is preventing me to do so, it outputs a black screen to every screenshot method I’ve tried so far. Does anyone know how to bypass this

  • Sandeep Arora December 7, 2019, 12:27 am

    Thanks for posting this. This helps! Though the Take-Screenshot stops working with “A generic error occurred in GDI+”. I referred another blog and improvised the code as below.

    if ((Test-Path $path) -eq $true) {
    [Drawing.Bitmap]$bmp = [System.Drawing.Image]::FromFile($path)
    } else {
    $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
    }

    $bmpNew = New-Object Drawing.Bitmap $bmp.Width, $bmp.height
    $graphics = [Drawing.Graphics]::FromImage($bmpNew)

    $rect = New-Object Drawing.Rectangle(0, 0, $bmpNew.Width, $bmpNew.Height)
    $graphics.DrawImage($bmp, $rect, 0, 0, $bmp.Width, $bmp.Height, [Drawing.GraphicsUnit]::Pixel)

    $bmp.Dispose()
    $bmp = $bmpNew

    $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
    $graphics.Dispose()

    $bmp.Save($path)

    $bmp.Dispose()
    $bmpNew.Dispose()

  • RickkeeC January 8, 2020, 9:46 am

    Nice, tried three, third time was a charm. Thanks!
    How might I modify to capture all monitors?