How can I capture the screen in Windows PowerShell? I need to be able to save the screen to disk.
5 Answers
You can also use .NET to take the screenshot programatically (which gives you finer control):
[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $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()
}
$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1000, 900)
screenshot $bounds "C:\screenshot.png"
![](../../users/profiles/267411.webp)
- 813
- 8
- 8
-
Great - how hard would it be to get this to capture the window of a specific application ? I am creating an IE instance like this : $ie = new-object -com "InternetExplorer.Application" - would it be possible to capture just the output of this window for instance ? – monojohnny Mar 14 '13 at 12:04
-
@jeremy tried on windows 10, doesn't work: output nothing. – user310291 Apr 15 '18 at 08:27
-
@user310291 the code itself still works, but you need to change the path from "C:\screenshot.png" to some location you can write to, e.g. your desktop. – Dreamer Jul 23 '18 at 08:00
This PowerShell function will capture the screen in PowerShell and save it to an automatically numbered file. If the -OfWindow switch is used, then the current window will be captured.
This works by using the built in PRINTSCREEN / CTRL-PRINTSCREEEN tricks, and it uses a bitmap encoder to save the file to disk.
function Get-ScreenCapture
{
param(
[Switch]$OfWindow
)
begin {
Add-Type -AssemblyName System.Drawing
$jpegCodec = [Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() |
Where-Object { $_.FormatDescription -eq "JPEG" }
}
process {
Start-Sleep -Milliseconds 250
if ($OfWindow) {
[Windows.Forms.Sendkeys]::SendWait("%{PrtSc}")
} else {
[Windows.Forms.Sendkeys]::SendWait("{PrtSc}")
}
Start-Sleep -Milliseconds 250
$bitmap = [Windows.Forms.Clipboard]::GetImage()
$ep = New-Object Drawing.Imaging.EncoderParameters
$ep.Param[0] = New-Object Drawing.Imaging.EncoderParameter ([System.Drawing.Imaging.Encoder]::Quality, [long]100)
$screenCapturePathBase = "$pwd\ScreenCapture"
$c = 0
while (Test-Path "${screenCapturePathBase}${c}.jpg") {
$c++
}
$bitmap.Save("${screenCapturePathBase}${c}.jpg", $jpegCodec, $ep)
}
}
Hope this helps
![](../../users/profiles/221631.webp)
- 7,039
- 2
- 24
- 37
-
Are there additional steps needed to get this to work on Windows 7 ? I'm getting the following error when running the function:"Unable to find type [Windows.Forms.Sendkeys]: make sure that the assembly containing this type is loaded." and then a further error "Unable to find type [Windows.Forms.Clipboard]: make sure that the assembly containing this type is loaded." , and then one more error (but I think because the previous two calls failed). – monojohnny Mar 21 '14 at 17:06
-
1You probably haven't loaded Winforms. I'd recommend you simply download the module this answer is now in: [RoughDraft](http://gallery.technet.microsoft.com/RoughDraft-cfeb6e98) – Start-Automating Mar 24 '14 at 22:29
For the sake of completion, this script allows you to take screenshots across multiple monitors.
Base code comes from Jeremy
[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
function screenshot($path)
{
$width = 0;
$height = 0;
$workingAreaX = 0;
$workingAreaY = 0;
$screen = [System.Windows.Forms.Screen]::AllScreens;
foreach ($item in $screen)
{
if($workingAreaX -gt $item.WorkingArea.X)
{
$workingAreaX = $item.WorkingArea.X;
}
if($workingAreaY -gt $item.WorkingArea.Y)
{
$workingAreaY = $item.WorkingArea.Y;
}
$width = $width + $item.Bounds.Width;
if($item.Bounds.Height -gt $height)
{
$height = $item.Bounds.Height;
}
}
$bounds = [Drawing.Rectangle]::FromLTRB($workingAreaX, $workingAreaY, $width, $height);
$bmp = New-Object Drawing.Bitmap $width, $height;
$graphics = [Drawing.Graphics]::FromImage($bmp);
$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size);
$bmp.Save($path);
$graphics.Dispose();
$bmp.Dispose();
}
Can be called with: screenshot "D:\screenshot.png"
![](../../users/profiles/1073358.webp)
- 1,369
- 1
- 19
- 26
Microsoft have a Powershell script available here:
http://gallery.technet.microsoft.com/scriptcenter/eeff544a-f690-4f6b-a586-11eea6fc5eb8
I have just tried it on a Windows 7 machine and it to work, using the commandline example provided:
Take-ScreenShot -screen -file "C:\image.png" -imagetype png
![](../../users/profiles/184456.webp)
- 5,531
- 15
- 56
- 78
-
Where do you place this .ps1 file so you don't have to type the entire network path in ? – Aaron Aug 27 '14 at 13:40
-
@Aaron, not quite sure how best to do this - but probably set it in Powershell profile (perhaps either by editing PATH variable, or using an alias) : this article may help :http://stackoverflow.com/questions/714877/setting-windows-powershell-path-variable – monojohnny Sep 02 '14 at 15:07
-
2Open with... produces no outcome. Input in console then invoking it produces no input either. This is Windows 10 and this thread has been here for years without producing input. – Danilo J. Bonsignore Feb 23 '17 at 22:49
Here is my solution for multi-monitor, which is a bit simpler than the current answer. It also will render screens properly if the user has a strange monitor config (stacked vertical, etc) without black bars.
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
$screens = [Windows.Forms.Screen]::AllScreens
$top = ($screens.Bounds.Top | Measure-Object -Minimum).Minimum
$left = ($screens.Bounds.Left | Measure-Object -Minimum).Minimum
$width = ($screens.Bounds.Right | Measure-Object -Maximum).Maximum
$height = ($screens.Bounds.Bottom | Measure-Object -Maximum).Maximum
$bounds = [Drawing.Rectangle]::FromLTRB($left, $top, $width, $height)
$bmp = New-Object System.Drawing.Bitmap ([int]$bounds.width), ([int]$bounds.height)
$graphics = [Drawing.Graphics]::FromImage($bmp)
$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
$bmp.Save("$env:USERPROFILE\test.png")
$graphics.Dispose()
$bmp.Dispose()
![](../../users/profiles/4868262.webp)
- 2,235
- 1
- 13
- 31