1

У меня есть какое-то программное обеспечение, которое не запускается на моей машине (Windows Vista), поэтому я запускаю его на виртуальной машине VMware (Windows XP) с использованием Unity, чтобы обеспечить удобство работы с пользователем.ТМ * 8 ')

Обычно это работает очень хорошо, но программное обеспечение позволяет мне запускать ссылки в веб-браузере, который, очевидно, запускает ссылку в новом веб-браузере в виртуальной машине, в то время как я хотел бы, чтобы ссылки запускались так, чтобы веб-страница заканчивалась на веб-браузер на моем хосте.

Кто-нибудь знает, возможно ли это и если да, то как?

Я могу настроить, какая команда запускается для запуска ссылки в приложении, поэтому, если для нее требуется выполнить конкретную команду для гостя, это не должно быть проблемой.

Благодарю.

2 ответа2

3

Я искал способ запуска приложений Windows (хост) с виртуальной машины Ubuntu (под VMWare Player). Я немного увлекся и написал сценарии клиента и сервера, перечисленные ниже. Гостевая ОС - это не Windows, поэтому для работы с гостем Windows потребуются некоторые изменения. Я использовал эту настройку, чтобы Git (работающий на гостевой системе Ubuntu) вызывал KDiff3 на хосте при слиянии.

Следующий скрипт Python (host_run_server.py) действует как сервер, принимающий команды от гостя. Он ожидает, что гость предоставит общий ресурс Samba с именем GUEST_ROOT_SHARE (установите его в верхней части скрипта), который открывает корень файловой системы. Этот общий ресурс сопоставлен с диском GUEST_DRIVE . Это необходимо для того, чтобы хост и гость могли получить доступ к одним и тем же файлам. В моем случае я уже смонтировал «Мои документы» в папке гостя, чтобы иметь возможность использовать git для файлов моего хоста.

import asyncore, asynchat
import os
import socket
import shlex, subprocess
import threading

# make the root / of the guest accessible as a samba share and map
# this share in the host to GUEST_DRIVE

HOST_IP = '192.168.126.1'
GUEST_IP = '192.168.126.129'
GUEST_ROOT_SHARE = 'root'
GUEST_DRIVE = 'K:'

TCP_PORT = 5005
BUFFER_SIZE = 1024
ENCODING = 'utf-8'

# map network drive
try:
    import win32wnet
    import pywintypes
    from win32netcon import RESOURCETYPE_DISK

    network_path = r'\\{}\{}'.format(GUEST_IP, GUEST_ROOT_SHARE)
    try:
        win32wnet.WNetAddConnection2(RESOURCETYPE_DISK, GUEST_DRIVE, network_path)
    except pywintypes.error as e:
        if (e.args[0] != 85 or
            win32wnet.WNetGetUniversalName(GUEST_DRIVE) != network_path):
            raise
except ImportError:
    pass


# allow GUI applications to pop to front on Windows
try:
    import win32gui
    from win32con import SPI_SETFOREGROUNDLOCKTIMEOUT

    result = win32gui.SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0)
    if result is not None:
        print("Failed:", result)
except ImportError:
    pass


class Handler(asynchat.async_chat):    
    def __init__(self, sock, map=None):
        asynchat.async_chat.__init__(self, sock, map=map)
        self.remote_ip, self.remote_port = self.socket.getpeername()
        self.log('connected')
        self.set_terminator(b'\x00')        
        self.data = b''
        self.state = 'cwd'

    def handle_close(self):
        remote_ip, remote_port = self.socket.getpeername()
        self.log('disconnected')
        self.close()

    def collect_incoming_data(self, data):
        self.data += data

    def found_terminator(self):
        if self.state == 'cwd':
            self.cwd = self.data.decode(ENCODING)
            self.state = 'cmd'
            self.data = b''
        elif self.state == 'cmd':
            self.cmd = self.data.decode(ENCODING)
            self.reply()
            self.state = 'end'

    def prepare(self):
        cwd = GUEST_DRIVE + self.cwd.replace('/', '\\')
        self.log('in {}'.format(cwd))
        os.chdir(cwd)
        cmd_args = []
        for arg in shlex.split(self.cmd):
            if arg.startswith('[FILE]'):
                arg = arg[6:].replace('/', '\\')
                if arg.startswith('\\'):
                    arg = GUEST_DRIVE + arg
            cmd_args.append(arg)
        return cwd, cmd_args

    def run(self, cwd, cmd_args):
        self.log('executing: {}'.format(' '.join(cmd_args)))
        try:
            p = subprocess.Popen(cmd_args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 shell=True)
            out, err = p.communicate()
            rcode = p.returncode
        except WindowsError as e:
            out = b''
            err = '{}: {}\n'.format(e.__class__.__name__, e.args[1]).encode(ENCODING)
            rcode = -1
        return rcode, out, err

    def reply(self):
        cwd, cmd_args = self.prepare()
        rc, out, err = self.run(cwd, cmd_args)
        self.push(str(len(out)).encode(ENCODING) +  b'\x00')
        if len(out):
            self.push(out)
        self.push(str(len(err)).encode(ENCODING) +  b'\x00')
        if len(err):
            self.push(err)
        self.push(str(rc).encode(ENCODING) + b'\x00')

    def log(self, msg):
        print("[{}:{}]\t{}".format(self.remote_ip, self.remote_port, msg))


class HandlerThread(threading.Thread):
    def __init__(self, sock):
        super().__init__()
        self.sock = sock

    def run(self):
        handler = Handler(self.sock)
        asyncore.loop(map=handler._map)


class Server(asyncore.dispatcher):
    def __init__(self, host, port, guest_ip):
        asyncore.dispatcher.__init__(self, map={})
        self.guest_ip = guest_ip
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind((host, port))
        self.listen(5)
        print("Service started. Listening on {} port {}."
              .format(host, port))

    def handle_accepted(self, sock, addr):
        (guest_ip, guest_port) = addr
        if guest_ip == self.guest_ip:
            ht = HandlerThread(sock)
            ht.start()
        else:
            print("Ignoring request from {}".format(guest_ip))


server = Server(HOST_IP, TCP_PORT, GUEST_IP)
asyncore.loop(map=server._map)

Ниже приведен скрипт для вызова на гостевой стороне (host_run.py).

#!/usr/bin/env python3

import asyncore, asynchat
import os
import socket
import sys
from optparse import OptionParser


HOST_IP = "192.168.126.1"
GUEST_IP = "192.168.126.129"
HOST_IS_WINDOWS = True

TCP_PORT = 5005
BUFFER_SIZE = 1024
ENCODING = 'utf-8'

STD_ENCODING = 'cp1252' if HOST_IS_WINDOWS else ENCODING


class HostRun(asynchat.async_chat):    
    def __init__(self, host, port):
        asynchat.async_chat.__init__(self)
        self.set_terminator(b'\x00')        
        self.data = b''
        self.state = 'stdout1'
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))

    def handle_connect(self):
        self.push(os.getcwd().encode(ENCODING) + b'\x00')
        self.push(command.encode(ENCODING) + b'\x00')

    def collect_incoming_data(self, data):
        self.data += data

    def found_terminator(self):
        if self.state == 'stdout1':
            stdout_len = int(self.data.decode(ENCODING))
            if stdout_len:
                self.set_terminator(stdout_len)
                self.state = 'stdout2'
            else:
                self.state = 'stderr1'
        elif self.state == 'stdout2':
            stdout = self.data.decode(STD_ENCODING)
            sys.stdout.write(stdout)
            self.set_terminator(b'\x00')
            self.state = 'stderr1'
        elif self.state == 'stderr1':
            stderr_len = int(self.data.decode(ENCODING))
            if stderr_len:
                self.set_terminator(stderr_len)
                self.state = 'stderr2'
            else:
                self.state = 'rc'
        elif self.state == 'stderr2':
            stderr = self.data.decode(STD_ENCODING)
            sys.stderr.write(stderr)
            self.set_terminator(b'\x00')
            self.state = 'rc'
        elif self.state == 'rc':
            rc = int(self.data.decode(ENCODING))
            sys.exit(rc)
            self.close_when_done()
        self.data = b''

    def handle_close(self):
        remote_ip, remote_port = self.socket.getpeername()
        print("%s:%s disconnected" %(remote_ip, remote_port))
        self.close()


parser = OptionParser()
(options, args) = parser.parse_args()

command = ' '.join(args)

HostRun(HOST_IP, TCP_PORT)

asyncore.loop()

Сценарии заботятся о переводе путей к файлам. Для того чтобы это работало, вам необходимо добавить пути, переданные в качестве аргументов клиентскому скрипту, с помощью [FILE]

Сначала запустите серверный скрипт на хосте. Теперь вы можете передавать команды клиентскому скрипту:

brecht@krubuntu ~ $ ./host_run.py dir [FILE]/home

Это переведет /home в K:\home и, таким образом, выполнит команду dir K:\home на хосте. Сервер отправляет вывод stdout/stderr и код возврата обратно клиенту, который выплевывает его обратно в приглашение оболочки:

 Volume in drive K is root
 Volume Serial Number is 64C2-522A

 Directory of K:\home

07/22/2012  22:13    <DIR>          .
12/04/2012  06:53    <DIR>          ..
02/28/2013  21:56    <DIR>          brecht
               0 File(s)              0 bytes
               3 Dir(s)  12,723,302,400 bytes free
1

Это может быть сделано, но я думаю, что для этого потребуется сетевое взаимодействие между гостем и хостом, и на каждом из них будет запущена вспомогательная программа. Вы также можете просто скопировать / вставить, если это не слишком хлопотно.

Какое программное обеспечение не будет работать в Vista? Я предполагаю, что вы пробовали режим совместимости и т.д.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .