一开始我想写个程序设置为 Windows 的默认浏览器。这样试图打开 URL 的时候,URL 会作为参数传给小程序。小程序通过 socket 转发到宿主机。宿主机上跑个 TCP 服务器不断打开传入的链接。

这样做主要有两个问题。一是有些网络设置的VBOX不能通过IP访问宿主机,这样这个方法就不能用了。二是宿主机要监听局域网传入的链接并自动打开,这样有安全隐患。因为局域网中的任意一个人都可以在短时间内传入一大堆链接然后直接卡掉整个 X Window。不过一个简单的异或加密可以解决这个问题。
这个解决方案即有无法弥补的缺陷,又有可以修复但会增加复杂度的缺陷。

然后想到 socket 除了 AF_INET 还有 AF_UNIX 可以用。遂搜索。
然后发现对于我目前使用的 Win7 兼容性不佳。

但思路还是建立基于文件通信的解决方案。

所以我想到用共享文件夹 + ionotifywait。
小程序把得到的 URL 写进共享文件里。
宿主机通过 ionotifywait 得知写事件,读取写入内容然后用浏览器打开。

这样用C代码和Bash脚本就好啦。

这个例子中我的url_handler.exe位于C:\\Users\\VM-Win7\\Desktop\\src\\vm_enhanced_intergration\\。共享文件夹在宿主机上是~/Downloads,客户机上是Z:\\

/* url_handler.exe for forwarding url to a shared file
* should be run on guest machine
* by rapiz
*/
#include<iostream>
#include<fstream>

char target[]="Z:\\.vm\\url"; // the path should be a file in the shared folder
int main(int argc, char** argv) {
    using namespace std;    
    ofstream fout(target);
    fout << argv[1] << endl;
}
#!/bin/sh
# should be run on host machine
FILE=~/Downloads/.vm/url
inotifywait -mq -e close_write $FILE | while read event
do
    cat $FILE
    $BROWSER $(cat $FILE)
done

设置一个程序为默认浏览器的过程并没有我想的那么简单,经过很多搜索之后在网上找到一段注册表。修改路径为你的程序的地址,保存为.reg导入。

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\WebMind]

@="WebMind Document"

[HKEY_CLASSES_ROOT\WebMind\Shell]

[HKEY_CLASSES_ROOT\WebMind\Shell\open]

[HKEY_CLASSES_ROOT\WebMind\Shell\open\command]

@="\"C:\\Users\\VM-Win7\\Desktop\\src\\vm_enhanced_intergration\\url_handler.exe\" \"%1\""

[HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice]

"Progid"="WebMind"

以上代码不能直接适用于你的电脑,要根据自己的情况修改路径。