.NET 开发效率高, 大行其道. 但却一直存在一个比较头疼的通病, 需要安装 .NET Framework, 尤其是.NET 2.0开发的软件. Windows XP 和 Windows 2003 默认都没有.NET 2.0 运行环境. 特别是一些精简版, 譬如"番茄花园"之类的版本, 连.NET2.0都装不上. 现在我们利用移动飞信的原理, 来解决以上的问题.
1. 安装完移动飞信2008后, 一般我们在 C:/Program Files/China Mobile/Fetion/ 目录里可以看到今天关键的主角:
Fetion.exe 启动飞信时首先会先运行这个程序, 用来检测本机是否有.NET环境, 如果有则运行FetionFx.exe, 如果没有则调用VMDotNet这个文件夹里的(v2.0.50727/FetionVM.exe)这个虚拟环境来处理.
FetionFx.exe 飞信真正的主程序, 需要.NET 2.0环境.
VMDotNet .NET2.0虚拟运行环境, 支持的版本为2.0.50727.
2. 介绍完这三个主角后, 我们来看一个简单的实例: 在一个没有安装过.NET 2.0的系统里, 把VMDotNet复制到D盘, 再复制一个你自己编写的.NET程序, 比如Test.exe, 放在D盘. 然后在开始菜单里的"运行"输入以下命令:
D://VMDotNet/v2.0.50727/FetionVM.exe D://Test.exe
你会发现神奇的事情出现了, Test.exe正常运行.
3. 你开始会有疑问了, 我如何像飞信那样直接运行, 而不是通过命令行呢?
1) 利用Fetion.exe来加载, 那样的话, 就需要把你自己的主程序改名为FetionFx.exe
2) 自己编写一个Win32程序来处理加载过程. 以下是详细步骤.
a) 在VS 2005/2008 里, 新建一个C++ Win32程序, 命名为XStart.
b) 在项目的源文件里找到XStart.cpp, 打开后找到里面的函数InitInstance代码, 并加入关键代码的处理.
c) 编译完成, 把XStart.exe复制到Test.exe和VMDotNet所在的目录, 运行XStart.exe, 大功告成!!!
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
nCmdShow = SW_HIDE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//===========我们加入的代码开始==============
using namespace std;
bool started = false;
try
{
char * args = (char*)lpArguments;
if(strcmp(args, "*") == 0)
{
::Sleep(3000);
}
TCHAR path[1024];
GetSystemDirectory(path, 1024);
wcscat_s(path, _T("//mscoree.dll"));
fstream _file(path, ios::in);
if(!_file)
{
//没有找到 mscoree.dll
::WinExec("VMDotNet/v2.0.50727/FetionVM.exe Test.exe", SW_SHOW);
started = true;
}
HKEY hkey;
if(::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE//Microsoft//.NETFramework//Policy//v2.0"), 0, KEY_READ, &hkey)
!= ERROR_SUCCESS)
{
//没有找到2.0版本
::RegCloseKey(hkey);
::WinExec("VMDotNet/v2.0.50727/FetionVM.exe Test.exe", SW_SHOW);
started = true;
}
DWORD type = REG_SZ;
DWORD data = 80;
if(::RegQueryValueEx(hkey, _T("50727"), NULL , &type, NULL, &data) != ERROR_SUCCESS)
{
//没有找到2.0.50727版本
::RegCloseKey(hkey);
::WinExec("VMDotNet/v2.0.50727/FetionVM.exe Test.exe", SW_SHOW);
started = true;
}
if(!started)
{
//直接运行
::RegCloseKey(hkey);
::WinExec("Test.exe", SW_SHOW);
}
}
catch(...)
{
::MessageBox(hWnd, _T("Sorry! Start program failed. /r/n/r/n对不起,程序启动失败!"), _T(" 启动失败 "), MB_ICONERROR);
}
::ExitProcess(0);
//=============我们加入的代码结束==============
return TRUE;
}