Screenshot.psm1
|
# This is a locally sourced Imports file for local development. # It can be imported by the psm1 in local development to add script level variables. # It will merged in the build process. This is for local development only. # region script variables # $script:resourcePath = "$PSScriptRoot\Resources" function Get-WindowLocation { [CmdletBinding()] param( [Parameter(Position = 0, Mandatory = $true)] [string]$WindowTitle ) Add-Type @" using System; using System.Runtime.InteropServices; namespace Screenshot { public class Window { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); // From an unknown user on Reddit: https://www.reddit.com/r/PowerShell/comments/2llb4u/comment/cm0e8fi/ private class unmanaged { // FindWindowByCaption [DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)] internal static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName); } // FindWindowByCaption public static IntPtr FindWindowByCaption(string Title) { return unmanaged.FindWindowByCaption(IntPtr.Zero, Title); } } public struct RECT { public int Left; // x position of upper-left corner public int Top; // y position of upper-left corner public int Right; // x position of lower-right corner public int Bottom; // y position of lower-right corner } } "@ $ProcessHandle = [Screenshot.Window]::FindWindowByCaption($WindowTitle) $Rectangle = [Screenshot.RECT]::New() if ([Screenshot.Window]::GetWindowRect($ProcessHandle, [ref]$Rectangle)) { return $Rectangle } else { throw "Failed to get window coordinates for '$WindowTitle'." } } function New-Screenshot { <# .EXTERNALHELP Screenshot-help.xml #> [CmdletBinding(DefaultParameterSetName = 'Coordinates', SupportsShouldProcess = $true)] param( [Parameter(ParameterSetName = 'Coordinates', Position = 0)] [Parameter(ParameterSetName = 'CoordinatesWithSize', Position = 0)] [int]$X = 0, [Parameter(ParameterSetName = 'Coordinates', Position = 1)] [Parameter(ParameterSetName = 'CoordinatesWithSize', Position = 1)] [int]$Y = 0, [Parameter(ParameterSetName = 'Coordinates', Position = 2)] [int]$Width, [Parameter(ParameterSetName = 'Coordinates', Position = 3)] [int]$Height, [Parameter(ParameterSetName = 'WindowTitle', Position = 0)] [string]$WindowTitle, [Parameter(ParameterSetName = 'WindowTitle', Position = 1)] [Parameter(ParameterSetName = 'Coordinates', Position = 4)] [Parameter(ParameterSetName = 'CoordinatesWithSize', Position = 2)] [string]$Path, [Parameter(ParameterSetName = 'WindowTitle', Position = 2)] [Parameter(ParameterSetName = 'Coordinates', Position = 5)] [Parameter(ParameterSetName = 'CoordinatesWithSize', Position = 3)] [string]$FileName = "Screenshot_{0}.jpg" -f (Get-Date -Format "yyyyMMdd_HHmmss") ) Add-Type -AssemblyName System.Windows.Forms, System.Drawing switch ($PSCmdlet.ParameterSetName) { "Coordinates" { if ($Width -eq 0) { $Width = [System.Windows.Forms.SystemInformation]::VirtualScreen.Width if ($X -gt 0) { $Width = $Width - $X } } if ($Height -eq 0) { $Height = [System.Windows.Forms.SystemInformation]::VirtualScreen.Height if ($Y -gt 0) { $Height = $Height - $Y } } break } "WindowTitle" { $Coordinates = Get-WindowLocation -WindowTitle $WindowTitle $X = $Coordinates.Left $Y = $Coordinates.Top $Width = $Coordinates.Right - $Coordinates.Left $Height = $Coordinates.Bottom - $Coordinates.Top break } } $Bitmap = [System.Drawing.Bitmap]::new($Width, $Height) $Graphic = [System.Drawing.Graphics]::FromImage($bitmap) $Graphic.CopyFromScreen($X, $Y, 0, 0, [System.Drawing.Size]::new($Width, $Height)) #region Screenshot Destination Path if([string]::IsNullOrEmpty($Path)) { $Path = Get-Location # Fallback to TEMP if current location is root of C:\ and user is not admin to avoid "Access Denied" error # not really necessary, but the previous behavior annoyed me lol if( $Path.ToString() -eq "C:\" -and ([Security.Principal.WindowsIdentity]::GetCurrent().Groups -notcontains 'S-1-5-32-544')) { $Path = $env:TEMP } } $DestinationPath = Join-Path -Path $Path -ChildPath $FileName #endregion Screenshot Destination Path #region Save Screenshot if ($PSCmdlet.ShouldProcess($DestinationPath, ("Saving Screenshot to path: '{0}'" -f $DestinationPath))) { try { $Bitmap.Save($DestinationPath, [System.Drawing.Imaging.ImageFormat]::Jpeg) Get-Item -Path $DestinationPath } catch { throw "Failed to save screenshot to path: '{0}'. Error: {1}" -f $DestinationPath, $_.Exception.Message } } #endregion Save Screenshot } |