Capturing a Hyper-V VM Screen to a file

Here is an interesting thing you can do with Hyper-V - with a little bit of code you can grab a copy of the virtual machine display and write it out to a bitmap file:

This is something that I use in a number of my long running scripts - as it provides a very handy logging trail if something goes wrong.  Something to note about this code: I use MSVM_VideoHead to get the resolution of the virtual machine display - and then hand that into GetVirtualSystemThumbnailImage.  You can also provide smaller dimensions than the current virtual machine display - in which case we will scale the bitmap image down for you.

Which is where this API gets its name from "GetVirtualSystemThumbnailImage" is actually used by Hyper-V Manager to generate the thumbnail image from the virtual machine.  It just also happens to support generating full resolution images as well.

Cheers,
Ben

Comments

  • Anonymous
    June 02, 2016
    This is not working.New-Object : Cannot find type [system.drawing.bitmap]: make sure the assembly containing this type is loaded.Must add[reflection.assembly]::loadfile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll")https://blogs.technet.microsoft.com/jamesone/2007/07/11/why-visual-studio-helps-powershell/
    • Anonymous
      June 03, 2016
      Thanks! I have fixed up the code.
  • Anonymous
    June 07, 2016
    I tried but i get this..... on a Windows Server 2012/ Windows PowerShell ISE Host Version 3.0/ machineCannot index into a null array.At C:\Users\Administrator.INEDIVIM\Downloads\vm-screen.ps1:10 char:1+ $xResolution = $video.CurrentHorizontalResolution[0]+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : NullArray Cannot index into a null array.At C:\Users\Administrator.INEDIVIM\Downloads\vm-screen.ps1:11 char:1+ $yResolution = $video.CurrentVerticalResolution[0]+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : NullArray A Using variable cannot be retrieved. A Using variable can be used only with Invoke-Command, Start-Job, or InlineScript in the script workflow. When it is used with Invoke-Command, the Using variable is valid only if the script block is invoked on a remote computer.At C:\Users\Administrator.INEDIVIM\Downloads\vm-screen.ps1:14 char:5+ $x = $using:xResolution+ ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : UsingWithoutInvokeCommand
  • Anonymous
    August 21, 2016
    Please help . $VMMS already defined$VMMS = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemManagementServiceYou cannot call a method on a null-valued expression.At C:\Users\root\Desktop\thumbnail.ps1:24 char:5+ $image = $VMMS.GetVirtualSystemThumbnailImage($VMCS, $x, $y).ImageData+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull Multiple ambiguous overloads found for "Copy" and the argument count: "4".At C:\Users\root\Desktop\thumbnail.ps1:30 char:5+ [System.Runtime.InteropServices.Marshal]::Copy($Image, 0, $BmpData.Scan0, $B ...+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest Exception calling "Save" with "1" argument(s): "A generic error occurred in GDI+."At C:\Users\root\Desktop\thumbnail.ps1:36 char:1+ (getVMScreenBMP $VMCS $xResolution $yResolution).Save($BMPName)+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ExternalException