IEventSource::CreateAggregator in PowerShell

Discussion about using the VirtualBox API, Tutorials, Samples.
Post Reply
NicolaF_
Posts: 1
Joined: 19. Nov 2018, 10:27

IEventSource::CreateAggregator in PowerShell

Post by NicolaF_ »

Hi,

I'm trying to create a script to automatically scale up a VM display when on an HiDPI display (code below), and I'm having trouble creating an aggregate event source (in monitorUntilStateChanges function):

Code: Select all

Exception setting "CreateAggregator": Cannot convert the "System.Object[]" value of type "Object[]" to type "array".
At C:\Users\xxxxxx\autoScaleVm.ps1:42 char:2
+     $agg = $console.EventSource.CreateAggregator($eventSources)
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : RuntimeException
What is the correct way to call IEventSource::CreateAggregator in PowerShell?

Best regards,
Nicolas

Code: Select all

$VM_NAME="Work"

$WIDTH_THRESHOLD=2000
$HEIGHT_THRESHOLD=1500
$HIDPI_SCALE=2
$LOWDPI_SCALE=1

## Constants
$VBOX = New-Object -ComObject VirtualBox.VirtualBox

$STATE_RUNNING = 5

$EVENT_OnMachineStateChanged = 32
$EVENT_OnGuestMonitorInfoChanged = 102

$LOCK_SHARED = 1

function waitForRunningState($machine) {
	Write-Host "Waiting for machine to be running..."

	$eventSource = $VBOX.EventSource
	$listener = $eventSource.CreateListener()
	[int[]] $eventTypes = $EVENT_OnMachineStateChanged
	$eventSource.RegisterListener($listener, $eventTypes, $false)
	while($machine.State -ne $STATE_RUNNING) {
		$event = $eventSource.getEvent($listener, -1)
	}
	$eventSource.UnregisterListener($listener)
	
	Write-Host "OK"
}

function monitorUntilStateChanges($machine) {
	Write-Host "Monitoring..."
	
	$session = New-Object -ComObject VirtualBox.Session
	$machine.LockMachine($session, $LOCK_SHARED)
	$console = $session.Console
	
	$eventSources = $VBOX.EventSource, $console.EventSource
	
	$agg = $console.EventSource.CreateAggregator($eventSources)
	$listener = $agg.CreateListener()
	$eventTypes = $EVENT_OnGuestMonitorInfoChanged, $EVENT_OnMachineStateChanged
	$agg.RegisterListener($listener, $eventTypes, $false)
	
	adjustScale $session
	
	while($true) {
		$event = $agg.getEvent($listener, -1)
		if($event.type -eq $EVENT_OnMachineStateChanged) {
			Write-Host "  Machine state changed, ending monitoring"
			break
		} else {
			Write-Host "  Monitor info changed"
			Write-Host "  Waiting for resolution to actually change..."
			$didChange = waitResolutionForChange
			if($didChange) {
				adjustScale $session
			} else {
				Write-Host "  Did not change"
			}
			
		}
		
	}
	
	agg.UnregisterListener($listener)
	$session.unlockMachine()
	
	Write-Host "End"
}

function adjustScale($session) {
	$fb = getFrameBuffer $session

	$currentScale = getScale $session
	$width = $fb.Width*$currentScale
	$height = $fb.Height*$currentScale
	Write-Host("  FrameBuffer size is $($width)x$($height) host pixels")
	if($width -gt $WIDTH_THRESHOLD -or $height -gt $HEIGHT_THRESHOLD) {
		setScale $session $HIDPI_SCALE
	} else {
		setScale $session $LOWDPI_SCALE
	}
}

function setScale($session, $scale) {
	$currentScale = getScale
	if($currentScale -ne $scale) {
		Write-Host("Scaling x$($scale)")
		$session.machine.SetExtraData("GUI/ScaleFactor", $scale)
	}
}

function getScale($session) {
	return $session.machine.GetExtraData("GUI/ScaleFactor")
}


function waitResolutionForChange($session) {
	$fb = getFrameBuffer $session
	
	$width = $fb.Width
	$height = $fb.Height
	
	Write-Host "    Waiting for resolution to actually change..."
	$i = 10
	while($i-- -gt 0 -and $width -eq $fb.Width -and $height -eq $fb.Height) {
		Start-Sleep -Seconds 1
	}
	
	return $width -ne $fb.Width -or $height -ne $fb.Height
}

function getFrameBuffer($session) {
	return $session.Console.Display.QueryFramebuffer(0)
}

$machine = $VBOX.findMachine($VM_NAME)

while($true) {
	waitForRunningState $machine
	monitorUntilStateChanges $machine
}
Post Reply