sethmlarson / virtualbox-python

Complete implementation of VirtualBox's COM API with a Pythonic interface.
https://pypi.org/project/virtualbox
Apache License 2.0
354 stars 75 forks source link

Exception when starting VBox process (Objects for SAFEARRAYS must be sequences) #134

Closed Onefivefournine closed 1 year ago

Onefivefournine commented 4 years ago
ENVIRONMENT
SUMMARY

I fail to start VBox session when running example code provided in readme. Machine I am trying to start is same as host Windows Server 2012 R2, it starts normally from the VBox GUI. I printed the arguments of method _call_method from library_base.py that seems to be a problem:

<bound method IMachine.LaunchVMProcess of <win32com.gen_py.VirtualBox Type Library.IMachine instance at 0x1043591361928>
> [<virtualbox.library_ext.session.ISession object at 0x000000F2FB0CE6C8>, 'gui', '']
STEPS TO REPRODUCE

vbox.py

import virtualbox
vbox = virtualbox.VirtualBox()
session = virtualbox.Session()
machine = vbox.find_machine("Windows")
progress = machine.launch_vm_process(session, "gui", "")
progress.wait_for_completion()
EXPECTED RESULTS

VBox process started

ACTUAL RESULTS
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\virtualbox\library_base.py", lin
e 201, in _call_method
    ret = method(*in_params)
  File "C:\Users\ADMINI~1\AppData\Local\Temp\2\gen_py\3.7\D7569351-1750-46F0-936E-BD127D5BC264x0x1x3.py", line 7181, in
LaunchVMProcess
    , aName, aEnvironmentChanges)
TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".\vbox.py", line 5, in <module>
    progress = machine.launch_vm_process(session, "gui", "")
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\virtualbox\library_ext\machine.p
y", line 183, in launch_vm_process
    type_p, environment)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\virtualbox\library.py", line 128
01, in launch_vm_process
    in_p=[session, name, environment])
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\virtualbox\library_base.py", lin
e 192, in _call
    return self._call_method(method, in_p=in_p)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\virtualbox\library_base.py", lin
e 214, in _call_method
    errobj.msg = exc.args[2][2]
IndexError: tuple index out of range
tutume commented 4 years ago

Any news about this issue? I have just started using this pibrary and I'm facing the same issue:

ENVIRONMENT Operating System: Windows 10 Pro 1909 Build 18363.657 Python version: Python 3.7.4 VirtualBox version: 6.1.2 r135662 VirtualBox SDK version: 6.1.2 virtualbox-python / pyvbox version: virtualbox-python (2.0.0)

The VM is working from the VBox GUI as usual.

I'm using the same basic steps to reproduce.

MickyMickyMike commented 4 years ago

I'm wondering about some updates as well. This issue started to appear since I was forced to upgrade VirtualBox to version 6.1.2.

I have been able to locate the cause of the error, which is the parameter "" in machine.launch_vm_process(session, "gui", ""). When it's changed to bytes "".encode() the process finishes without error.

sethmlarson commented 4 years ago

@MickyMickyMike Could you dig a little deeper into this change and potentially contribute a fix? Thanks! :)

tutume commented 4 years ago

Hi, I'm not a developer, so would take a lot o time to get into the real issue here, yet, I'm trying to understand the issue and help.

One test I did was install an older version of Virtualbox (5.2.36) and tested the same code and it worked:

import virtualbox
vbox = virtualbox.VirtualBox()
session = virtualbox.Session()
machine = vbox.find_machine("linux")
progress = machine.launch_vm_process(session, "gui","")
progress.wait_for_completion()

Went back to my main machine and tried to debug the code running with the VBox 6.1.2. With no luck. So, digging into the SDK, I found the file sdk/bindings/glue/python/sample/vboxshell.py and a function startVm(ctx, mach, vmtype) where has a variable named asEnv=[] (an older SDK didn't have this variable) followed by a line: progress = mach.launchVMProcess(session, vmtype, asEnv) And testing the vboxshell.py it works with VBox 6.1.2.

Then, found the following code in the library.py:

        #line 12680
        def launch_vm_process(self, session, name, environment):
            ....
            #line 12798-12799
            if not isinstance(environment, basestring):
                raise TypeError("environment can only be an instance of type basestring")

So I commented the lines 12798-12799 and tested again. It worked.

For now I will be using like this, but I will not submit a PR as I don't really know what is wrong and how to fix it as I believe the type enforcement must have a reason.

MickyMickyMike commented 4 years ago

I don't have exactly time to dig deeper into the problem, sorry. Frankly, I don't think I have the skill neither. I can commit this "workaround fix" if you want.

iondex commented 4 years ago

The problem seems to be an API change in VirtualBox API version 6_1. The method signature of LaunchVMProcess changed from:

HRESULT LaunchVMProcess (
        [in] ISession * aSession,
        [in] BSTR aName,
        [in] BSTR aEnvironment,
        [out, retval] IProgress * * aProgress
 );

(API version 5)

to:

HRESULT LaunchVMProcess (
        [in] ISession * aSession,
        [in] BSTR aName,
        [in] SAFEARRAY(BSTR) aEnvironmentChanges,
        [out, retval] IProgress * * aProgress
);

(API version 6_1)

A temporary fix would be allowing passing list as the environment parameter of launch_vm_process and passing empty list to this method.

        #line 12680
        def launch_vm_process(self, session, name, environment):
            ....
            #line 12798-12799
            if if not (isinstance(environment, basestring) or isinstance(environment, list)):
                raise TypeError("environment can only be an instance of type basestring or list")
# works
import virtualbox
vbox = virtualbox.VirtualBox()
session = virtualbox.Session()
machine = vbox.find_machine("Windows")
progress = machine.launch_vm_process(session, "gui", [])
progress.wait_for_completion()
sethmlarson commented 4 years ago

Nice investigative work! Could you open a PR to fix this issue in the README / docs?

sethmlarson commented 1 year ago

I no longer have time to maintain this library, so am closing this issue.