客戶端數據上報的簡單實現

發佈到外網的安裝包和客戶端程序,常常須要向後臺上報一些數據。實現數據上報的方法有不少,其中最簡單的方法是,用IE靜默打開一個帶有查詢字符串的URL。這樣,只要在apache上部署一個簡單的腳本,就能統計數據上報了。

先看下安裝包中數據上報的實現,nsis代碼以下: shell

ExecShell "open" "iexplore.exe" "http://127.0.0.1" SW_HIDE

這個腳本對應到win32的API,是ShellExecute。奇怪的是,nsis腳本在安裝包上運行的很好,IE可以靜默打開,而到了客戶端上,用ShellExecute並設置了SW_HIDE,老是不能隱藏。 apache

接着我在網上找到了用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得到: url

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進程了。  spa

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腳本也可以優雅的上報數據了:) 
相關文章
相關標籤/搜索