发布到外网的安装包和客户端程序,经常需要向后台上报一些数据。实现数据上报的方法有很多,其中最简单的方法是,用IE静默打开一个带有查询字符串的URL。这样,只要在apache上部署一个简单的脚本,就能统计数据上报了。
先看下安装包中数据上报的实现,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脚本也能够优雅的上报数据了:)
时间: 2024-10-13 06:47:14