先看下安装包中数据上报的实现,nsis代码如下:
ExecShell "open" "iexplore.exe" "http://127.0.0.1" SW_HIDE
这个脚本对应到win32的API,是ShellExecute。奇怪的是,nsis脚本在安装包上运行的很好,IE能够静默打开,而到了客户端上,用ShellExecute并设置了SW_HIDE,总是不能隐藏。
接着我在网上找到了用CreateProcess打开IE的方法.如下代码展示了从注册表中读取IE的路径,然后用CreateProcess隐藏打开的方法。注意CreateProcess的第二个参数,url的前面要带上open。
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(szIEPath, TEXT("open http://127.0.0.1"), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
{
return -1;
}
IE的路径可由如下的GetIEPath获得:
BOOL GetIEPath(LPTSTR lpszPath, int nLen)
{
BOOL bSuccess = FALSE;
do
{
HKEY hKey = NULL;
DWORD dwSizeOfPath = 0;
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE"),
0,
KEY_READ,
&hKey))
{
break;
}
if (ERROR_SUCCESS != RegQueryValueEx(hKey, TEXT(""), NULL, NULL, NULL, &dwSizeOfPath))
{
break;
}
if (dwSizeOfPath >= nLen)
{
break;
}
if (ERROR_SUCCESS != RegQueryValueEx(hKey, TEXT(""), NULL, NULL, (LPBYTE)lpszPath, &dwSizeOfPath))
{
break;
}
lpszPath[dwSizeOfPath + 1] = TEXT('\0');
bSuccess = TRUE;
} while(FALSE);
return bSuccess;
}
写了这么多代码,现在问题解决了么?我在自己的机器上测试一切正常!
可是...
到了安装IE11的电脑上,nsis脚本的ExecShell和客户端的CreateProcess,打开的IE都展示在用户的面前,我们总不能让用户知道我们在收集数据吧:)
最终,找到了一种更简单的方法,只要调用两个win32接口即可。这样也不需要创建额外的IE进程了。
HINTERNET hInternet1 = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);
if (hInternet1)
{
HINTERNET hInternet2 = InternetOpenUrl(hInternet1,szOpenUrlAddr, NULL, NULL,INTERNET_FLAG_NO_CACHE_WRITE,NULL);
InternetCloseHandle(hInternet1);
if (hInternet2)
{
InternetCloseHandle(hInternet2);
}
}
这样实现,我们上报数据,从任务管理器里也不留痕迹,而且代码更短!
把这段代码移植到NSIS插件中,nsis脚本也能够优雅的上报数据了:)