触摸屏应用相关技术之四——终端监控
终端监控集成了http服务作为其重要部分,因此能够通过http交互接受并处理指令,或者返回终端的适时状态。考虑到系统的安全性,http协议交互采用了md5验证和ip验证,并附带时间戳。
经过比较选择,本文采用了以下链接作为httpServer原型
http://www.codeproject.com/KB/IP/mhttpsrv.aspx 它具备以下特征:多线程、能够处理标准的http GET请求,实现了统一的日志类。
Md5实现采用了
http://www.koders.com/c/fid736BC59EAF6EB77661FB371C054D6B464644266B.aspx?s=suck
    控制
通过http通道,可以向终端发送控制命令,包括:更新参数设置(默认首页、长时间无人点击自动切回首页时间等)、指定访问页面等。
1.Wake On Lan
由于触摸屏特殊性,远程开机是终端控制必不可少的组成部分。
如果触摸屏主机的网卡、主板、电源均支持WOL,而且已知该网卡的mac地址,则可以通过网络向发送包含该mac地址信息的wol packet,实现远程开机。
采用此机制的VC实现请参考:
http://www.codeproject.com/KB/IP/WOL.aspx?fid=211282&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2155379&fr=26
而java实现的关键代码如下:

public static void wake(String ipStr,String macStr) throws IOException{
         byte[] macBytes = getMacBytes(macStr);
         byte[] bytes = new byte[6 + 16 * macBytes.length];
         for (int i = 0; i < 6; i++) {
             bytes[i] = (byte) 0xff;
         }
         for (int i = 6; i < bytes.length; i += macBytes.length) {
             System.arraycopy(macBytes, 0, bytes, i, macBytes.length);
         }
         String destIP = "255.255.255.255";
         if(ipStr!=null)
             destIP = ipStr;
         InetAddress address = InetAddress.getByName(destIP);
         DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, PORT);
         DatagramSocket socket = new DatagramSocket(10000);
         socket.send(packet);
         socket.close();
         
         System.out.println("Wake-on-LAN packet sent.");
         
     }


2.程序关机
关键代码如下:

BOOL CJSCallApp::MySystemShutdown()
 {
    HANDLE hToken; 
    TOKEN_PRIVILEGES tkp; 

    // Get a token for this process. 

    if (!OpenProcessToken(GetCurrentProcess(), 
         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
       return( FALSE ); 

    // Get the LUID for the shutdown privilege. 

    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 
         &tkp.Privileges[0].Luid); 

    tkp.PrivilegeCount = 1;  // one privilege to set    
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

    // Get the shutdown privilege for this process. 

    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 
         (PTOKEN_PRIVILEGES)NULL, 0); 

    if (GetLastError() != ERROR_SUCCESS) 
       return FALSE; 

    // Shut down the system and force all applications to close. 

    if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE | EWX_POWEROFF, 0)) 
       return FALSE; 
    return TRUE;
 }



3.程序重启系统

BOOL CJSCallApp::MySystemReboot()
 {
     HANDLE hToken; 
    TOKEN_PRIVILEGES tkp; 

    // Get a token for this process. 

    if (!OpenProcessToken(GetCurrentProcess(), 
         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
       return( FALSE ); 

    // Get the LUID for the shutdown privilege. 

    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 
         &tkp.Privileges[0].Luid); 

    tkp.PrivilegeCount = 1;  // one privilege to set    
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

    // Get the shutdown privilege for this process. 

    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 
         (PTOKEN_PRIVILEGES)NULL, 0); 

    if (GetLastError() != ERROR_SUCCESS) 
       return FALSE; 

    // Shut down the system and force all applications to close. 

    if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0)) 
       return FALSE; 

    return TRUE;
 }



4.禁止屏幕保护和省电模式

//禁用屏保
      BOOL bScrActive;
      SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &bScrActive, 0);
      if (bScrActive)
         SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); 
     //禁用电源保护
      m_nLowpowerTimeout = 0;
      m_nPoweroffTimeout = 0;
      SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, 0, &m_nLowpowerTimeout, 0);
      SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0, &m_nPoweroffTimeout, 0);
      SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
      SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);


5.隐藏任务栏和桌面

//隐藏任务栏,桌面
     ::ShowWindow(::FindWindow("Shell_TrayWnd",NULL),SW_HIDE);
     ::ShowWindow(::FindWindow("ProgMan",NULL),SW_HIDE);



6.添加IE信任站点

void CJSCallApp::setZoneMap(LPCTSTR sites)
 {
     string ss = sites;
     string sp = ";";
     vector<string> v2 = tokenize(ss, sp ,false,"");
     CRegisterKey   key;  
     CString   str; 
     DWORD dw;
     BOOL ret;

     CString dn = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Domains\\");  
     CString kn = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range");  
     int id = 0;
     for(int i=0; i<v2.size(); i++){
         string s = v2[i];
         //去掉http://
         int pos = s.find("://");
         if(pos!=-1)
             s =s.substr(pos+3);
         bool bIP = true;
         vector<string> v1 = tokenize(s, "." ,false,"");
         for(int j=0; j<v1.size(); j++){
             for (int k=0;k<v1[j].size(); k++ ){
                 char cc = v1[j][k];
                 if(cc>'9' || cc<'0')
                 {
                     bIP = false;
                     break;
                 }
             }
             if(!bIP)
                 break;
         }
         dw=2;
         if(!bIP){
             for(int j=1; j<v1.size(); j++){
                 if(j==1)
                     s=v1[j];
                 else
                     s += "."+v1[j];
             }
             s+="\\"+v1[0];
             CString dns;
             dns.Format("%s%s",dn,s.c_str());
             key.Open(HKEY_CURRENT_USER,(LPCTSTR)dns);
             ret = key.Write("http",dw);
             key.Close();
         }else{
             CString kns;
             id++;
             kns.Format("%s%d",kn,id);
             key.Open(HKEY_CURRENT_USER,(LPCTSTR)kns);  
             ret = key.Write(":Range",s.c_str());
             ret = key.Write("http",dw);
             key.Close();
         }
     }
 }



7.设置IE每次访问页面检查(内容的更新能立即反映到终端)

CRegisterKey   key;  
      key.Open(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
      DWORD dw=0x3;
      key.Write("SyncMode5",dw);
      key.Close();




    监视
1.屏幕快照
调用API CreateCompatibleBitmap可以将打印屏幕到bitmap,但是采用bitmap格式,文件尺寸较大,不利于网络传输,在VC6.0下,我们可以请求于GdiPlus.lib,将bitmap格式转换为互联网广泛使用的jpeg格式。
关键代码如下:
 

CBitmap* m_pBackBitmap;
         …
         //NEW资源(调用一次重新拷贝一次)
         if (m_pBackBitmap != NULL)
         {
                 delete m_pBackBitmap;
                 m_pBackBitmap = NULL;
         }
         m_pBackBitmap = new CBitmap();
         CDC ScrDC,MemDC;
         ScrDC.CreateDC("DISPLAY", NULL, NULL, NULL);
         MemDC.CreateCompatibleDC(&ScrDC);
         m_pBackBitmap->CreateCompatibleBitmap(&ScrDC,width,height);
         MemDC.SelectObject(m_pBackBitmap);
         //开始拷贝
         MemDC.BitBlt(xStartPt, yStartPt, width, height,&ScrDC,xToCopy,yToCopy,SRCCOPY);
         ScrDC.DeleteDC();
         MemDC.DeleteDC();
 …
 void CScreenSnap::snap(LPCTSTR fpath)//fpath保存路径
 {
     int width = ::GetSystemMetrics(SM_CXSCREEN);
     int height = ::GetSystemMetrics(SM_CYSCREEN);
     this->CopyScreenToBitmap(0,0,width,height,0,0);
       //创建位图句柄

     HBITMAP   hBitmap;
     hBitmap=(HBITMAP)m_pBackBitmap->GetSafeHandle();

     //获取jpg or png编码

    CLSID encoderClsid;
    Bitmap bitmap(hBitmap,NULL);
   CString ImageFileName=fpath;
   if(ImageFileName.Find(".jpg")>0)
     GetEncoderClsid(L"image/jpeg",&encoderClsid);
   else
     GetEncoderClsid(L"image/png",&encoderClsid);
    //JPG编码
    EncoderParameters encoderPara;
    encoderPara.Count=1;
    encoderPara.Parameter[0].Guid=EncoderQuality;
    encoderPara.Parameter[0].Type=EncoderParameterValueTypeLong;
    encoderPara.Parameter[0].NumberOfValues=1;
    ULONG quality=50;
    encoderPara.Parameter[0].Value=&quality;
    //调用GDI+保存
    bitmap.Save(ImageFileName.AllocSysString(),&encoderClsid,&encoderPara);
 }



2.本进程的内存占用情况

string CJSCallApp::getMyMemSta()
 {
     HANDLE hp = GetCurrentProcess();
     PROCESS_MEMORY_COUNTERS pmc;
     if (! GetProcessMemoryInfo(hp, &pmc, sizeof (pmc)))
         // 调用 api 失败,退出
         return "";
     CString str;
     str.Format("phy: %d M,virtual: %d M",
         (pmc.WorkingSetSize/1024)/1024,
         (pmc.PagefileUsage/1024)/1024);
     CloseHandle(hp);
     return str;
 }



3.全局内存占用情况

string CJSCallApp::getGlobalMemStatus()
 {
   MEMORYSTATUS   memStatus;  
   memStatus.dwLength   =   sizeof(MEMORYSTATUS);  
    
   GlobalMemoryStatus(&memStatus);  
    
   DWORD   total   =   (DWORD)memStatus.dwTotalPhys;  
   DWORD   avail   =   (DWORD)memStatus.dwAvailPhys;  
   DWORD   vir     =   (DWORD)memStatus.dwTotalVirtual;  
   DWORD   avail_vir = (DWORD)memStatus.dwAvailVirtual; 
    
   //转化为MB  
   total   =   (total/1024)/1024;  
   avail   =   (avail/1024)/1024;  
   vir       =   (vir/1024)/1024;  
   avail_vir = (avail_vir/1024)/1024;

   CString   memsta;  
   memsta.Format("phy:%ld/%ld MB,virtual:%ld/%ld MB",
       avail,total,avail_vir,vir);   
   return memsta;
 }



4.CPU使用情况