![我可以从 VMware 客户虚拟机内部启动主机操作系统上的程序或 Web 链接吗?](https://linux22.com/image/1277106/%E6%88%91%E5%8F%AF%E4%BB%A5%E4%BB%8E%20VMware%20%E5%AE%A2%E6%88%B7%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%86%85%E9%83%A8%E5%90%AF%E5%8A%A8%E4%B8%BB%E6%9C%BA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%8A%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%88%96%20Web%20%E9%93%BE%E6%8E%A5%E5%90%97%EF%BC%9F.png)
我有一些软件无法在我的计算机上运行(Windows Vista),因此我使用 unity 在 VMware VM(Windows XP)中运行它,以获得无缝的用户体验。TM *8')
这通常很有效,但该软件允许我在 Web 浏览器中启动链接,这显然会在 VM 内的新 Web 浏览器中启动链接,而我希望启动链接以便网页最终出现在我的 Host 上的 Web 浏览器上。
有人知道这是否可能,如果可能,如何做?
我可以配置运行哪个命令来启动应用程序中的链接,因此如果它需要在客户机上运行特定命令,那应该没有问题。
谢谢。
答案1
我一直在寻找一种从 Ubuntu 虚拟机(在 VMWare Player 下)启动 Windows 应用程序(主机)的方法。我有点忘乎所以,写了下面列出的客户端和服务器脚本。客户操作系统不是 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 输出和返回代码发送回客户端,客户端将其返回到 shell 提示符:
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
答案2
可以这样做,但我认为这需要客户机和主机之间的网络通信,以及在每个主机上运行的辅助程序。如果不太麻烦,您也可以选择直接复制/粘贴。
哪些软件无法在 Vista 上运行?我猜你试过兼容模式等。