Execute process inside VM

Discussion about using the VirtualBox API, Tutorials, Samples.
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Execute process inside VM

Post by Bypus »

Hello,

Sorry if there is a similar post of this on this forum but i couldn't find it anywhere.

I'm trying to launch an executable (.exe) on a Japanese Windows 7 guest, using Python 2.7 on the host (Windows 7).
So far, this is what i've done :

Code: Select all

mgr = vboxapi.VirtualBoxManager(None, None)
vbox = mgr.vbox
machine = vbox.findMachine("W7 32-bit JAP")
session = mgr.openMachineSession(machine)
console = session.console
try:
    snapshot = machine.findSnapshot("SnapshotW7x86Jap")
    progress = session.machine.restoreSnapshot(snapshot)
    progress.waitForCompletion(10000)
    if progress.resultCode ! =0: 
        raise Exception, "Couldn't restore VM snapshot"
    mgr.closeMachineSession(session)

    # Launching VM
    session = mgr.mgr.getSessionObject(vbox)
    progress = machine.launchVMProcess(session, "gui", "")
    progress.waitForCompletion(10000)
    if progress.resultCode != 0:
        raise Exception, "Couldn't start VM"
    console = session.console

    while console.state != mgr.constants.MachineState_FirstOnline:
        print console.state
        time.sleep(3)
    guestsession=console.guest.createSession("test","pass","","")
    guestsession.waitFor(1,20000)
For the second part here is what i have tried but i've got many errors and i know don't know where to go :

Code: Select all

    path = glob.glob("K:¥‎****¥‎****¥‎****¥‎****¥‎*****.exe") # (Full path in the real script)
    arg = []
    evtc = []
    flag[0] = 2
    progress=guestsession.processCreate(path, arg, evtc, flag, 0)
    progress.waitFor(2,20000)
Does anybody have a idea ? Thanks in advance.
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

We can't really help you like this, there is no context, no error info, no standalone piece of code. Please read the posting guildelines
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

Sorry, i'm not used to forums.

I didn't really know what additional info could be useful.
As i said, i am looking for a way to launch a Windows .exe on a Virtual Machine running Windows 7 32-bits Japanese.
The VM is hosted on Windows 7 Professional 64-bits.
I am using the version 5.1.28-117968 of VirtualBox with the extension pack and the version 5.1.28 of the API.
For the connection type I was adviced win32com.

The script i'm trying to write uses Python 2.7 and shall be executed on the host machine only (Windows 7) and is basically what I wrote in the previous post.
The guest (W7 Japanese) is a virgin installation of Windows.

As for the errors, since i tested many things, i will not be able find them back. The most recent was something about

Code: Select all

 pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, u'GuestProcessWrap', u'The guest execution service is not ready (yet)', None, 0, -2135228411), None)
I'm not a veteran of Python or the vboxapi so i was wandering for help to understand how the API worked combined with win32com.

Thank you :)
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

In the Code samples, 3rd one, there is one for executing a process inside a VM and reading its output.
While the example is for an older version of VirtualBox and in Java, you would follow the same steps in Python.

If that still doesn't help, please put together a standalone python script that I can run locally that illustrates your problem
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

Here is what i transcripted from Java, i don't know if it's exact but i'll look more into it tomorrow :

Code: Select all

import vboxapi
import glob
import win32com.client
import time

# def errorIfNull(systemProperty):
# 	value = sys.property(systemProperty)
# 	if value != None:
# 		return value
# 	else:
# 		raise RuntimeException(systemProperty + "is not set")


mgr = vboxapi.VirtualBoxManager(None, None)
vbox = mgr.vbox
machine = vbox.findMachine("W7 32-bit JAP")
session = mgr.openMachineSession(machine) # locks at this point
# machine.lockMachine(session, mgr.constants.LockType_Shared)

# Console wouldn't initialize without the two block under
snapshot = machine.findSnapshot("SnapshotW7x86Jap")
progress = session.machine.restoreSnapshot(snapshot)
progress.waitForCompletion(10000)
if progress.resultCode!=0:
	raise Exception, "Timed out restoring VM snapshot"
mgr.closeMachineSession(session)

# Launch VM
session = mgr.mgr.getSessionObject(vbox)
progress = machine.launchVMProcess(session, "gui", "")
progress.waitForCompletion(10000)
if progress.resultCode != 0:
	raise Exception, "Timed out starting VM"
console = session.console
try:
	guestSess = console.guest.createSession("test","","","")
	try:
		guestSess.waitFor(1, 30000)
		if guestSess.status != mgr.constants.GuestSessionStatus_Started: raise Exception, "Guest Session did not start after 30 sec"
		time.sleep(5) # Let Windows stabilize

		path = "notepad.exe"
		flag = [5]
		process = guestSess.processCreate(path, None, None, flag, 0)
		es = process.eventSource
		el = es.createListener()
		es.registerListenener(el, mgr.constants.VBoxEventType_Any, False)

		try:
			print "Guest process created"
			# pwr = process.waitFor(mgr.constants.ProcessWaitForFlag_Start.value, 30000)
			# print "Process wait result: " + pwr
			wr = process.waitForArray((mgr.constants.ProcessWaitForFlag_StdOut, mgr.constants.ProcessWaitForFlag_Terminate), 200)
			print "Process wait result: " + wr
			keepLooking = True
			while keepLooking:
				ev = es.getEvent(el, 200)
				if ev != None:
					es.eventProcessed(el, ev)
				stdOut = process.read(1, 64, 0)
				print str(stdOut)
				if "Terminated" not in str(process.status):
					keepLooking = not keepLooking
			print "Process exit code: " +  process.exitCode
		finally:
			es.unregisterListener(el)
			if "Terminated" not in str(process.status):
				process.teminate()
	finally:
		print "Session close"
		guestSess.close()
except:
	print "???"
finally:
	print "Machine unlock"
	session.unlockMachine()
I couldn't initialize the console without launching the VM, maybe i'm doing it wrong. (That's why i didn't put together the standalone python script)
It compiles but doesn't launch "notepad.exe".
Here is the lof at the end:

Code: Select all

Session close
???
Machine unlock
Exception RuntimeError: 'sys.meta_path must be a list of import hooks' in <bound method VirtualBoxManager.__del__ of <vboxapi.VirtualBoxManager object at 0x02D57DD0>> ignored
[Finished in 12.2s]
Thank you for your time
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

Bypus wrote:It compiles but doesn't launch "notepad.exe".
That normal it wouldn't launch "notepad.exe", you don't have a GUI session when executing via VirtualBox. You have a non-GUI environment which is not linked to your GUI session. notepad.exe requires a GUI, so it won't work...
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

Do I not in my version by adding:

Code: Select all

progress = machine.launchVMProcess(session, "gui", "")
(Did I forget something ?)
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

That's how to start the VM, wvich is irrelevant to executing commands in it.
When you run a guest session and process, those are created from the guest additions process which runs as a service.
Services don't have gui access normally.
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

After correcting many syntaxe error here is the code:

Code: Select all

mgr = vboxapi.VirtualBoxManager(None, None)
vbox = mgr.vbox
machine = vbox.findMachine("W7 32-bit JAP")
session = mgr.openMachineSession(machine) # locks at this point

# Console wouldn't initialize without the two block under
snapshot = machine.findSnapshot("SnapshotW7x86Jap")
progress = session.machine.restoreSnapshot(snapshot)
progress.waitForCompletion(10000)
if progress.resultCode!=0:
	raise Exception, "Timed out restoring VM snapshot"
mgr.closeMachineSession(session)

# Launch VM
session = mgr.mgr.getSessionObject(vbox)
progress = machine.launchVMProcess(session, "gui", "")
progress.waitForCompletion(10000)
if progress.resultCode != 0: 
	raise Exception, "Timed out starting VM"
# machine.lockMachine(session, mgr.constants.LockType_Shared)

console = session.console

try:
	print "Session creation..."
	guestSess = console.guest.createSession("test","", None, None)

	try:
		print "Session created"

		guestSess.waitFor(1, 30000)
		if guestSess.status != mgr.constants.GuestSessionStatus_Started:
			raise Exception, "Guest Session did not start after 30 sec"
		time.sleep(5) # Let Windows stabilize

		path = "notepad.exe ‎C:¥‎ユーザー¥‎test.txt"
		flag = [mgr.constants.ProcessCreateFlag_WaitForStdOut]
		process = guestSess.processCreate(path, None, None, flag, 0)
		print "Process created "

		es = process.eventSource
		el = es.createListener()
		evtType = [mgr.constants.VBoxEventType_Any]
		es.registerListener(el, evtType, False)

		try:
			print "Guest process created"
			pwff1 = [mgr.constants.ProcessWaitForFlag_Start]
			pwr = process.waitFor(pwff1[0], 30000) # Blocked here ?
			print pwr
			print "Process wait result: " + pwr

			keepLooking = True
			while keepLooking:
				ev = es.getEvent(el, 200)
				if ev != None:
					es.eventProcessed(el, ev)
				pwff2 = [mgr.constants.ProcessWaitForFlag_StdOut]
				print pwff2
				wr = process.waitForArray(pwff2, 200)
				print wr
				print "Process wait result: " + wr
				stdOut = process.read(1, 64, 0)
				print str(stdOut)
				print str(process.status)
				if "Terminated" not in str(process.status):
					break
			print "Process exit code: " +  process.exitCode
		finally:
			es.unregisterListener(el)
			if "Terminated" not in str(process.status):
				process.terminate()
	finally:
		print "Session close"
		guestSess.close()
except Exception as e:
	if hasattr(e, 'message'):
		print(e.message)
	else:
		print(e)
finally:
	print "Machine unlock"
	session.unlockMachine()
And here is the log:

Code: Select all

Session creation...
Session created
Process created 
Guest process created
Session close

Machine unlock
Exception RuntimeError: 'sys.meta_path must be a list of import hooks' in <bound method VirtualBoxManager.__del__ of <vboxapi.VirtualBoxManager object at 0x02DC7E30>> ignored
[Finished in 9.8s]
As we can see, it fails after "Guest process created". I have tried some tests with "print"s and "Exception"s but nothing appears on the log. I don't know what's wrong

Edit: path variable for less error.
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

there are several errors in your code:
- The win32com.client import fails, but is not needed so not sure why you had this in the first place
- The sample code specifically says that using StdOut event will fail, yet you use it
- The sample code checks if "Terminated" is the process status. If yes, it stops the loop. Your code stops the loop if it ISN'T - so it directly exit.
- The executable path must not contain arguments. Use the 2nd parameters of processCreate() for that purpose
- Your sample code does not have a UTF-8 header, python will fail to run it
- You hide exception messages within your try-catch block. Python does not work the same than Java, you can't just copy paste it I'm afraid.

I managed to make it work on my computer, after several fixing of your code with this, which requires a running VM with Windows started and ready:

Code: Select all

# -*- coding: utf-8 -*-
import vboxapi
import glob
import time

mgr = vboxapi.VirtualBoxManager(None, None)
vbox = mgr.vbox
machine = vbox.findMachine("myVM")
session = mgr.openMachineSession(machine) # locks at this point

# Launch VM
session = mgr.mgr.getSessionObject(vbox)
machine.lockMachine(session, mgr.constants.LockType_Shared)

console = session.console

try:
   print "Session creation..."
   guestSess = console.guest.createSession("test","test", None, None)

   try:
      print "Session created"

      guestSess.waitFor(1, 30000)
      if guestSess.status != mgr.constants.GuestSessionStatus_Started:
         raise Exception, "Guest Session did not start after 30 sec"
      time.sleep(5) # Let Windows stabilize

      path = "c:/windows/system32/arp.exe"
      flag = [mgr.constants.ProcessCreateFlag_WaitForStdOut]
      process = guestSess.processCreate(path, None, None, flag, 0)
      print "Process created "

      es = process.eventSource
      el = es.createListener()
      evtType = [mgr.constants.VBoxEventType_Any]
      es.registerListener(el, evtType, False)

      try:
         print "Guest process created"
         pwff1 = [mgr.constants.ProcessWaitForFlag_Start]
         pwr = process.waitFor(pwff1[0], 30000) # Blocked here ?

         keepLooking = True
         while keepLooking:
            ev = es.getEvent(el, 200)
            if ev != None:
               es.eventProcessed(el, ev)
            stdOut = process.read(1, 64, 0)
            print str(stdOut)
            print str(process.status)
            if "Terminated" in str(process.status):
               break
         print "Process exit code: " +  process.exitCode
      finally:
         es.unregisterListener(el)
         if "Terminated" not in str(process.status):
            process.terminate()
   finally:
      print "Session close"
      guestSess.close()
except Exception as e:
   print(e)
   if hasattr(e, 'message'):
      print(e.message)
finally:
   print "Machine unlock"
   session.unlockMachine()
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

I used the win32com.client in previous tests and just copied it without thinking haha. Removed it but import fail still shows
I tried to use StdOut because i didn't know if it was implemented since the sample was on the 4.X API
Oops, I was lost in tests and forgot how processCreate() worked
Sorry, forgot to copy the header since i had some commented code, but it was there

With all that cleared, there still is an error

Code: Select all

Session creation...
Session created
Session close
(-2147352567, 'Exception occurred.', (0, u'GuestSessionWrap', u'The specified user was not able to logon on guest', None, 0, -2135228411), None)
I installed the additions and disabled the limitation for blank password (Computer Configuration, etc), tried with:

Code: Select all

- guestSess = console.guest.createSession("test", "", None, None)
- guestSess = console.guest.createSession("test", None, None, None)
- guestSess = console.guest.createSession("Real-Username", None, None, None)
- guestSess = console.guest.createSession("Real-Username", "", None, None)
But same error "The specified user was not able to logon on guest"
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

Windows doesn't allow any kind of "remote" or "system" login for users with blank password, so that's expected
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

Oh ok
So, I added a password to the admin session
I'm not sure i understood how createSession() worked.
I am putting the Admin credentials as arguments and it still can't logon
Does the function create a new session apart from the Administrator and sets the arguments as credentials ?
noteirak
Site Moderator
Posts: 5229
Joined: 13. Jan 2012, 11:14
Primary OS: Debian other
VBox Version: OSE Debian
Guest OSses: Debian, Win 2k8, Win 7
Contact:

Re: Execute process inside VM

Post by noteirak »

If you get the same error as earlier but with a user that has a password, you should look into the event log of Windows why it failed.
Also, don't think the virtualbox guest session has something to do with a GUI session. They are just concepts. All is handled in the guest additions service.
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Bypus
Posts: 33
Joined: 26. Sep 2017, 11:52

Re: Execute process inside VM

Post by Bypus »

Which log, guest or host ?

Edit : because i can't find anything on host's and guest's is half Japanese :?
Last edited by Bypus on 28. Sep 2017, 13:52, edited 1 time in total.
Post Reply