触摸屏应用相关技术之四——终端监控
终端监控集成了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使用情况