-
-
Save BenjaminArmstrong/e6e4c771b5553b6c15788a3406feb934 to your computer and use it in GitHub Desktop.
| $VMName = "VM 1" | |
| $BMPName = "C:\Users\benja\Desktop\test.bmp" | |
| Add-Type -AssemblyName "System.Drawing" | |
| $VMCS = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -Filter "ElementName='$($VMName)'" | |
| # Get the resolution of the screen at the moment | |
| $video = $VMCS.GetRelated("Msvm_VideoHead") | |
| $xResolution = $video.CurrentHorizontalResolution[0] | |
| $yResolution = $video.CurrentVerticalResolution[0] | |
| function getVMScreenBMP { | |
| param | |
| ( | |
| $VM, | |
| $x, | |
| $y | |
| ) | |
| $VMMS = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemManagementService | |
| # Get screenshot | |
| $image = $VMMS.GetVirtualSystemThumbnailImage($VMCS, $x, $y).ImageData | |
| # Transform into bitmap | |
| $BitMap = New-Object System.Drawing.Bitmap -Args $x,$y,Format16bppRgb565 | |
| $Rect = New-Object System.Drawing.Rectangle 0,0,$x,$y | |
| $BmpData = $BitMap.LockBits($Rect,"ReadWrite","Format16bppRgb565") | |
| [System.Runtime.InteropServices.Marshal]::Copy($Image, 0, $BmpData.Scan0, $BmpData.Stride*$BmpData.Height) | |
| $BitMap.UnlockBits($BmpData) | |
| return $BitMap | |
| } | |
| (getVMScreenBMP $VMCS $xResolution $yResolution).Save($BMPName) |
I have an error with a new version of the script:
"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."
I have Powershell v5.0.10586.117 on the host (2012 R2) and 2012 R2 guest from Image Factory (https://github.com/BenjaminArmstrong/Hyper-V-PowerShell/tree/master/Image-Factory)
Gah! Okay, take three. This one should work.
Perfect! Thank you.
Awesome, works great still on Server 2019 :)
This is supposed to be run on the host machine, not inside the guest machine, right?
I can confirm this works on Windows PowerShell, but not modern PowerShell (powershell.exe, not pwsh.exe), at least on my machine. This is awesome!
EDIT (18 June 2024): The code as-is only works in Windows PowerShell, but that's because there are newer APIs for using WMI/CIM in modern PowerShell.
For my purposes, I used runspaces to continue using the old APIs, but you can see a modern implementation in strawgate's HyperV-OCR project (a friend found that for me).
Runspace alternative:
$s = New-PSSession -UseWindowsPowerShell
Invoke-Command -Session $s -ScriptBlock {
# Call above code, basically.
#
# If you want to reference external variables:
# $MyVar becomes $using:MyVar
}
Good point - I have updated to code to be cleaner on scoping