Skip to content

Instantly share code, notes, and snippets.

@Eric2XU
Forked from BenjaminArmstrong/SaveVMBitmap.ps1
Last active May 22, 2018 12:34
Show Gist options
  • Save Eric2XU/9ad06f4998fd3bf8952ad95ce6c01171 to your computer and use it in GitHub Desktop.
Save Eric2XU/9ad06f4998fd3bf8952ad95ce6c01171 to your computer and use it in GitHub Desktop.
Sample PowerShell script that shows you how to create a .BMP file of the display of a Hyper-V virtual machine.
# This script wouldn't be possible without the orginal work done by
# Ben Armstrong, https://blogs.msdn.microsoft.com/virtual_pc_guy/2016/05/27/capturing-a-hyper-v-vm-screen-to-a-file/
# My version improves image file size by using JPEG and also creates a complete
# script that will created images for a given time frame
#####################
# Script House Keeping
#####################
$Error.Clear()
Clear-Host
#####################
# Script Options
#####################
# Local VM Name
$VMName = "OSD"
# Image Type: https://msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat(v=vs.110).aspx
$ImageType = "jpeg"
# Direectory to Dump images
$SavePath = "c:\temp\vmphotos\"
# Amount of time to run
$RunTimeInSeconds = "3600"
# Amount of time between images, images can be almost 1mb in size, while we dedump recent images
# it will add up, if you are running for a long time think about increasing this.
$ImageTimeGapInSeconds = "1"
######################
# Script Assemblies
#####################
Add-Type -AssemblyName "System.Drawing"
######################
# Script Functions
######################
function get-VMScreenShot ($vm,$x,$y) {
# Collect VM Object
$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
}
function write-VMScreenShot ($SavePath,$ImageType) {
$FinalImageName = "$($SavePath)\$(Get-Date -Format o | foreach {$_ -replace ":", "."}).$($ImageType)"
$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]
(get-VMScreenShot $VMCS $xResolution $yResolution).Save($FinalImageName,$ImageType)
}
######################
# Main Script
######################
$RunUntil = (Get-Date).AddSeconds($RunTimeInSeconds)
While ($RunTimeInSeconds -gt (Get-Date)) {
write-VMScreenShot -SavePath $SavePath -ImageType $ImageType
# DeDump last 20
get-childitem $SavePath | sort name -Descending | select -first 20 | sort name | get-filehash | group -property hash | where { $_.count -gt 1 } | % { $_.group | select -skip 1 } | del
# Sleep to not overwhelm system
sleep -Seconds $ImageTimeGapInSeconds
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment