Public/Get-PShot.ps1
<#
.SYNOPSIS Captures a PowerShell Screenshot .DESCRIPTION Captures a PowerShell Screenshot and saves the image in the -Directory $Env:TEMP\PShot by default .LINK https://osdeploy.com/module/functions/get-pshot .NOTES 21.1.23 Initial Release #> function Get-PShot { [CmdletBinding()] Param ( #Directory where the screenshots will be saved #Default = $Env:TEMP\PShots [string]$Directory = $null, #Saved files will have a PShot prefix in the filename [string]$Prefix = 'PShot', #Delay before taking a PShot in seconds #Default: 0 (1 Count) #Default: 1 (>1 Count) [uint32]$Delay = 0, #Total number of screenshots to capture #Default = 1 [uint32]$Count = 1, #Additionally copies the PShot to the Clipboard [switch]$Clipboard = $false, #Screenshot of the Primary Display only [switch]$Primary = $false ) begin { #====================================================================================================== # Gather #====================================================================================================== $PShotInfo = $(Invoke-Expression (Get-Content (Get-Module -List PShot).Path -Raw)) $MyPictures = (New-Object -ComObject Shell.Application).NameSpace('shell:My Pictures').Self.Path #====================================================================================================== # Adjust Delay #====================================================================================================== if ($Count -gt '1') {if ($Delay -eq 0) {$Delay = 1}} #====================================================================================================== # Determine Task Sequence #====================================================================================================== $LogPath = '' $SMSTSLogPath = '' try { $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction SilentlyContinue $IsTaskSequence = $true $LogPath = $TSEnv.Value('LogPath') $SMSTSLogPath = $TSEnv.Value('_SMSTSLogPath') Write-Host "Task Sequence is running" } catch [System.Exception] { $IsTaskSequence = $false $LogPath = '' $SMSTSLogPath = '' } #====================================================================================================== # Set AutoPath #====================================================================================================== if ($Directory -eq '') { if ($IsTaskSequence -and (Test-Path $LogPath)) { $AutoPath = Join-Path -Path $LogPath -ChildPath "PShots" } elseif ($IsTaskSequence -and (Test-Path $SMSTSLogPath)) { $AutoPath = Join-Path -Path $SMSTSLogPath -ChildPath "PShots" } elseif ($env:SystemDrive -eq 'X:') { $AutoPath = 'X:\MININT\SMSOSD\OSDLOGS\PShots' } elseif (Test-Path $MyPictures) { $AutoPath = Join-Path -Path $MyPictures -ChildPath "PShots" } else { $AutoPath = "$Env:TEMP\PShots" } } else { $AutoPath = $Directory } #====================================================================================================== # Usage #====================================================================================================== Write-Verbose '======================================================================================================' Write-Verbose "PShot $($PShotInfo.ModuleVersion)" Write-Verbose "$($PShotInfo.Description)" Write-Verbose '======================================================================================================' Write-Verbose 'Get-PShot [[-Directory] <String>] [[-Prefix] <String>] [[-Delay] <UInt32>] [[-Count] <UInt32>] [-Clipboard] [-Primary]' Write-Verbose '' Write-Verbose '-Directory Directory where the screenshots will be saved' Write-Verbose ' If this value is not set, Path will be automatically set between the following:' Write-Verbose ' Defaults = [LogPath\PShots] [_SMSTSLogPath\PShots] [My Pictures\Pshots] [$Env:TEMP\PShots]' Write-Verbose " Value = $AutoPath" Write-Verbose '' $DateString = (Get-Date).ToString('yyyyMMdd_HHmmss') Write-Verbose "-Prefix Pattern in the file name $($Prefix)_$($DateString).png" Write-Verbose " Default = PShot" Write-Verbose " Value = $Prefix" Write-Verbose '' Write-Verbose '-Count Total number of screenshots to capture' Write-Verbose ' Default = 1' Write-Verbose " Value = $Count" Write-Verbose '' Write-Verbose '-Delay Delay before capturing the screenshots in seconds' Write-Verbose ' Default = 0 (Count = 1) | Default = 1 (Count > 1)' Write-Verbose " Value = $Delay" Write-Verbose '' Write-Verbose '-Clipboard Additionally copies the screenshot to the Clipboard' Write-Verbose " Value = $Clipboard" Write-Verbose '' Write-Verbose '-Primary Captures screenshot from the Primary Display only for Multiple Displays' Write-Verbose " Value = $Primary" Write-Verbose '======================================================================================================' #====================================================================================================== # Load Assemblies #====================================================================================================== Add-Type -Assembly System.Drawing Add-Type -Assembly System.Windows.Forms #====================================================================================================== } process { foreach ($i in 1..$Count) { #====================================================================================================== # Determine Task Sequence (Process Block) #====================================================================================================== $LogPath = '' $SMSTSLogPath = '' try { $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction SilentlyContinue $IsTaskSequence = $true $LogPath = $TSEnv.Value('LogPath') $SMSTSLogPath = $TSEnv.Value('_SMSTSLogPath') Write-Host "Task Sequence is running" } catch [System.Exception] { $IsTaskSequence = $false $LogPath = '' $SMSTSLogPath = '' } #====================================================================================================== # Set AutoPath (Process Block) #====================================================================================================== if ($Directory -eq '') { if ($IsTaskSequence -and (Test-Path $LogPath)) { $AutoPath = Join-Path -Path $LogPath -ChildPath "PShots" } elseif ($IsTaskSequence -and (Test-Path $SMSTSLogPath)) { $AutoPath = Join-Path -Path $SMSTSLogPath -ChildPath "PShots" } elseif ($env:SystemDrive -eq 'X:') { $AutoPath = 'X:\MININT\SMSOSD\OSDLOGS\PShots' } elseif (Test-Path $MyPictures) { $AutoPath = Join-Path -Path $MyPictures -ChildPath "PShots" } else { $AutoPath = "$Env:TEMP\PShots" } } else { $AutoPath = $Directory } Write-Verbose "AutoPath is set to $AutoPath" #====================================================================================================== # Determine AutoPath #====================================================================================================== if (!(Test-Path "$AutoPath")) { Write-Verbose "Creating snapshot directory at $AutoPath" New-Item -Path "$AutoPath" -ItemType Directory -Force -ErrorAction Stop | Out-Null } #====================================================================================================== # DPI Scaling #====================================================================================================== $PShotDpiScaling = Get-PShotDpiScaling Write-Verbose "Screen DPI Scaling is $([Math]::round($PShotDpiScaling, 0)) Percent" #====================================================================================================== # Screen Resolution #====================================================================================================== if ($Primary) { Write-Verbose "Gathering Primary Display only" $PShotScreen = Get-PShotPrimaryScreen } else { $PShotScreen = Get-PShotVirtualScreen } Write-Verbose "Virtual Screen resolution is $($PShotScreen.Width) x $($PShotScreen.Height)" # Get Physical Screen Resolution [int32]$PShotScreenWidth = [math]::round($(($PShotScreen.Width * $PShotDpiScaling) / 100), 0) [int32]$PShotScreenHeight = [math]::round($(($PShotScreen.Height * $PShotDpiScaling) / 100), 0) Write-Verbose "Physical Screen resolution is $($PShotScreenWidth) x $($PShotScreenHeight)" #====================================================================================================== # Delay #====================================================================================================== Write-Verbose "Delay $Delay Seconds" Start-Sleep -Seconds $Delay #====================================================================================================== # Generate Bitmap #====================================================================================================== $PShotBitmap = New-PShotBitmap $PShotGraphics = [System.Drawing.Graphics]::FromImage($PShotBitmap) $PShotGraphics.CopyFromScreen($PShotScreen.Left, $PShotScreen.Top, 0, 0, $PShotBitmap.Size) #====================================================================================================== # Copy the PShot to the Clipboard # https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.clipboard.setimage?view=net-5.0 #====================================================================================================== if ($Clipboard) { Write-Verbose "Copying PShot to the Clipboard" Add-Type -Assembly System.Drawing Add-Type -Assembly System.Windows.Forms [System.Windows.Forms.Clipboard]::SetImage($PShotBitmap) } #====================================================================================================== # Save the PShot to File # https://docs.microsoft.com/en-us/dotnet/api/system.drawing.image.tag?view=dotnet-plat-ext-5.0 #====================================================================================================== $DateString = (Get-Date).ToString('yyyyMMdd_HHmmss') $FileName = "$($Prefix)_$($DateString).png" Write-Verbose "Saving PShot $i of $Count to to $AutoPath\$FileName" $PShotBitmap.Save("$AutoPath\$FileName") #====================================================================================================== # Close #====================================================================================================== $PShotGraphics.Dispose() $PShotBitmap.Dispose() #====================================================================================================== # Return Get-Item #====================================================================================================== Get-Item "$AutoPath\$FileName" #====================================================================================================== } } End {} } |