Powershell - 如何在屏幕锁定时获取窗口截图?

时间:2015-12-01 08:44:30

标签: windows powershell screenshot

屏幕锁定时有没有办法获取窗口的图像?

我使用RoughDraft的Get-Screenshot来捕获窗口截图,但显然它在屏幕锁定时无法正常工作。

在我们的环境中,我们使用Powershell,因此我的脚本如下所示:

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public static class Win32Api
{
  public static uint WM_CLOSE = 0x10;

  [System.Runtime.InteropServices.DllImportAttribute( "User32.dll", EntryPoint =  "GetWindowThreadProcessId" )]
  public static extern int GetWindowThreadProcessId ( [System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, out int lpdwProcessId );

  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  public static extern IntPtr FindWindow(IntPtr sClassName, String sAppName);

  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

  [DllImport("kernel32.dll")]
  public static extern uint GetLastError();
}
"@
....cut....

try {
    while ($ProcessActive.Id -ne $null) {
    $find_window = [Win32Api]::FindWindow([IntPtr]::Zero, $wname )
    $ProcessActive = Get-Process -Id $app.Id -ErrorAction SilentlyContinue

    $get_pid = [Win32Api]::GetWindowThreadProcessId( $find_window, [ref] $dbPID );

    if ($find_window -ne 0 -And $dbPID -eq $app.Id) {
        Write-Host "[ERROR]  Warning window found:" $find_window -NoNewline
        Write-Host ", and has parent PID:" $dbPID

    if (Test-Path warning-$dbPID-scr0.JPEG) {
       Write-Host "[STATUS] Old screenshot file exist, cleaning..."
       Remove-Item warning-$dbPID-scr0.JPEG
    }
        Get-ScreenShot -OfWindow -Path warning-$dbPID-scr

        if (Test-Path warning-$dbPID-scr0.JPEG) {
           Write-Host Saved screenshot as warning-$dbPID-scr0.JPEG
        }
    else {
      Write-Host "[ERROR]  Error while saving screenshot!"
    }

        $zero = [IntPtr]::Zero
        $send_close = [Win32Api]::SendMessage( $find_window, [Win32Api]::WM_CLOSE, $zero, $zero )

        Write-Host "[ERROR]  Exit with code 1 (this is not good)"
        exit 1
    }
catch {
   $ErrorMessage = $_.Exception.Message
   Write-Host "We'v got this: $ErrorMessage"
}

1 个答案:

答案 0 :(得分:1)

要获取窗口的屏幕截图,应用程序必须调用GetDC / GetDCEx以获取代表窗口屏幕区域的设备上下文。

这总是返回一个代表显示器上窗口位置的DC,并被剪切到显示器上的窗口可见区域。

这意味着,当您绘制到Windows DC时,您将直接绘制到显示设备上,尽管剪裁时不能在窗口可见区域的边界外绘制。

这也意味着,如果你使用这个DC作为源DC来捕获窗口的屏幕截图,那么在显示设备上,“现在”的窗口部分实际上没有可见的部分像素。

如果(并且这是一个非常大的IF),所讨论的窗口实际上支持WM_PRINT消息,您可以使用PrintWindow API来鼓励窗口将自己绘制到您提供的DC上。这应该使它从头开始绘画,你可能会得到一个很好的Windows内容副本。