VC实现系统热键激活后台服务程序

转载 2015年06月27日 14:31:50
摘要: 本文给出了一种通过设置系统热键来呼出在系统后台隐藏运行的服务程序的一种方法,通过这种方法,可以实现后台服务程序在必要的时候同用户的交互设置。

  引言

  通常情况下,用于后台监控的服务程序(Service)是没有界面的,甚至也没有提供任务栏图标,因此绝大多数情况下服务程序是无法同用户进行交互的。但是在实际应用中,这些服务程序虽然绝大多数时间是在后台运行,但是在某些必要的情况下还是需要用户的干预并同用户进行一些必要的交互操作。但是由于服务程序没有提供任何可供交互操作之用的界面,因此如何将其从后台激活(即呼出)成为解决此问题的一个关键。本文下面就给出一种通过设置系统热键的方法来激活运行于后台的服务程序。

  设计思路

  尽管从理论上可以有许多方法来激活后台运行的服务程序,比如可以通过寻找服务程序的窗口标题名而得到其窗口指针,然后再向此窗口发送消息使其出现到前台;也可以通过系统快照对当前系统进程进行枚举,然后再将其激活到前台。但是以上这些方法都需要另外编写应用程序,对后台服务程序的激活实际是再这些应用程序中进行的,这样的处理方式显然十分不便,最好的方法是对程序的激活和隐藏处理均在服务程序内部完成。因此可以考虑接收系统发出的消息,如果通过设置全局钩子对设置事件进行拦截捕获,显然是相当烦琐的。在此考虑使用系统热键来激活后台服务程序,其实现过程非常简单,只需先向操作系统添加一个全局原子(Atom),然后再向操作系统登记一个热键,当程序在后台运行期间一旦有此热键按下,操作系统将会抛出系统消息WM_HOTKEY,所以服务程序只需在WM_HOTKEY消息响应函数中添加相应代码即可实现服务程序的后台激活。

  系统热键的注册

  根据前面的介绍,不难写出为后台服务程序添加对系统热键响应的功能代码。首先通过函数GlobalFindAtom()查询本服务程序所对应的全局原子是否已存在于全局原子表中,如果发现,则说明系统中已经存在有此服务,程序退出。如果没有发现,则通过GlobalAddAtom()函数向全局原子表添加一个字串,并获取得到一个唯一标识此字串的原子。以上两函数原型分别为:

ATOM GlobalFindAtom(LPCTSTR lpString);
ATOM GlobalAddAtom(LPCTSTR lpString);

  其中,输入参数为一个描述原子的字符串,如果GlobalFindAtom()从全局原子表中找到了指定的字串,那么将返回此字串对应的原子,否则返回0。GlobalAddAtom()如果创建成功,将返回一个新创建的原子。
接下来,为了能在程序运行期间捕获到系统热键,需要通过RegisterHotKey()定义一个系统范围的热键。该函数原形如下:

BOOL RegisterHotKey(HWND hWnd, // 接收热键响应的窗口句柄
int id, // 热键的标识
UINT fsModifiers, // 控制键标志
UINT vk // 虚拟键值
);

  其中,热键标识id必须是一个范围在0xC000到0xFFFF之间的全局唯一的值,为了避免可能引起的热键冲突,通常把GlobalAddAtom()返回的原子作为参数传入,而且GlobalAddAtom()返回值的范围同id参数的允许范围是完全一致的。参数fsModifiers定义了同虚拟键值vk同时按下而产生出系统热键消息WM_HOTKEY的控制键组合,如MOD_ALT、MOD_CONTROL、MOD_SHIFT和MOD_WIN等。在本例中将要设定的系统热键为Alt+Ctrl+R,因此,参数fsModifiers和vk分别设置为MOD_ALT| MOD_CONTROL和VK_R。有关系统热键的注册实现方法可以整理如下:

// 获取当前窗口句柄
HWND handle = GetSafeHwnd();
// 寻找HotKey对应的原子是否存在于原子列表
if(GlobalFindAtom("Hotkey") == 0)
{
// 如果没有存在于原子列表,则创建一个原子
id = GlobalAddAtom("Hotkey");
//注册全局热键Ctrl + Alt + R
RegisterHotKey(handle, id, CONTROL + ALT, R);
}
else // 如果HotKey已经存在于原子列表,则终止程序运行
PostQuitMessage(0);

  服务程序的隐藏与激活

  服务程序除了被激活后同用户的交互,绝大部分时间都是在后台隐藏运行的,不仅界面是不可视的,而且在任务列表中也不应当出现。关于界面的隐藏比较简单,可以通过向ShowWindow()函数设置SW_HIDE参数来实现,而在任务列表中的隐身则一般的做法是通过调用系统内核Kernel32.DLL的RegisterServiceProcess()函数将其设置成为一个服务进程,这样,在任务列表中也实现了隐身。但是RegisterServiceProcess()函数并非一个标准的API函数,使用起来有点烦琐。首先要通过GetModuleHandle()函数得到Kernel32.DLL模块的句柄,并由此通过GetProcAddress()函数进一步得出RegisterServiceProcess()函数在Kernel32.DLL中的入口地址,最后才能使用RegisterServiceProcess()函数。该函数原型声明如下:

DWORD RegisterServiceProcess(DWORD dwProcessId,DWORD dwType);

  其第一个参数指定了将要注册为服务进程的进程标识,参数dwType指定是去注册一个服务进程(为1时)还是去卸载一个服务进程(为0时)。其具体服务注册过程如下:

typedef DWORD (WINAPI *RSP)(DWORD dwProcessId,DWORD dwType);
// 获取Kernel32.DLL模块句柄
HMODULE m_hKernel = ::GetModuleHandle("Kernel32.DLL");
// 得到RegisterServiceProcess()函数入口地址
RSP m_rsp = (RSP)::GetProcAddress(m_hKernel, "RegisterServiceProcess");
// 注册当前进程为服务进程
m_rsp(::GetCurrentProcessId(),1);

  在服务程序后台运行期间,一旦有系统热键Alt+Ctrl+R按下,将发出系统热键消息WM_HOTKEY,该消息的消息响应函数不能通过ClassWizard来添加,而只能手工完成消息映射。在消息响应函数中,通过对消息参数 wParam的判断可以确定出是否是本服务程序所设定的系统热键,如果是,通过ShowWindow(SW_SHOW)将程序界面显示出来,以进行同用户的交互操作:

void CServiceDlg::OnHotKey(WPARAM wParam, LPARAM lParam)
{
// 判断是否是本服务程序设置的系统热键
if (wParam == id)
{
……
// 在此发送WM_PAINT消息,在OnPain()中通过
// ShowWindow(SW_SHOW)将界面设置为可视
PostMessage(WM_PAINT, 0, 0);
}
}

  系统热键的卸载

  由于前面将系统热键、全局原子等都注册到系统,因此必须在服务程序退出之前将其卸载,否则将导致下次注册时的失败。函数UnregisterHotKey()负责完成对系统热键的释放,GlobalDeleteAtom()将全局原子从全局原子列表删除。

  小结

  通过本文所述方法为后台运行的系统服务程序添加此热键呼出功能可以真正实现程序的后台隐蔽运行、热键激活,非常有利于管理员和用户的管理与使用。本文所述程序在Windows 2000 Professional下,由Microsoft Visual C++ 6.0编译通过。


http://blog.chinaunix.net/uid-574845-id-2733968.html

C#为应用程序注册快捷键

在应用中,我们可能会需要实现像Ctrl+C复制、Ctrl+V粘贴这样的快捷键,本文简单介绍了它的实现,并给出了一个实现类。(1)建立一个类文件,命名为HotKey.cs,代码如下:using Syst...
  • ismycxp
  • ismycxp
  • 2007年07月19日 14:56
  • 3323

如何将应用程序注册为系统服务

将任何应用程序注册成后台服务程序,即:系统启动后该程序可以自动启动,并且在前台不要出现运行窗口。 解决办法:需要使用Windows提供的两个工具instsrv.exe和srvany.exe。(Win...
  • flyfranker
  • flyfranker
  • 2011年09月19日 12:56
  • 17022

VC实现系统热键激活后台服务程序

2003-07-10 17:37 作者: 中国电波传播研究所青岛分所郎锐 出处: yesky 摘要: 本文给出了一种通过设置系...
  • forzy
  • forzy
  • 2007年06月26日 08:55
  • 993

VC实现系统热键激活后台服务程序(界面)

http://hi.baidu.com/aleizxl/blog/item/cab92e163972464920a4e9f2.html 摘要: 本文给出了一种通过设置系统热键来呼出在系统后台隐藏运行的...
  • greenfire
  • greenfire
  • 2009年02月15日 18:04
  • 877

怎样把任意exe程序注册成windows系统服务

某gae代理软件每次开机都需要手动启动,就算添加成开机启动项,在win8.1下权限的管理更加严格,开机时并不能成功启动软件(无人值守时开机),因此在网上搜索把exe注册成系统服务的办法,找到论坛两个帖...
  • hellojoy
  • hellojoy
  • 2016年08月19日 12:30
  • 4800

VC实现系统热键激活后台服务程序

摘要: 本文给出了一种通过设置系统热键来呼出在系统后台隐藏运行的服务程序的一种方法,通过这种方法,可以实现后台服务程序在必要的时候同用户的交互设置。   引言   通常情况下,用于后台监控...
  • jacksonfan
  • jacksonfan
  • 2015年06月27日 14:31
  • 504

vc 如何注册系统热键

原文链接:http://www.cnblogs.com/VCdog/archive/2010/04/07/1706228.html 纵观整个搜索引擎,这个样的主题文章也很多,就是没有自己亲自...
  • zzstack
  • zzstack
  • 2016年01月12日 09:19
  • 541

VC添加全局热键的方法

全局热键定义 VirtualKey.h /************************************************************************/ // Vi...
  • lujianfeiccie2009
  • lujianfeiccie2009
  • 2012年04月25日 17:09
  • 4050

如何在你的java程序中注册系统级热键

所谓系统级热键就是指一组快捷键,不论当前系统焦点在哪个程序中,只要按下该键,程序就能够捕捉该事件并进行相关处理。该功能在应用程序中是非常有用的,比如系统自带的 “win+L”自动锁屏,QQ中默认...
  • ycb1689
  • ycb1689
  • 2012年07月11日 18:42
  • 846

exe程序注册成windows系统服务

C#写好的.exe程序,今天突然需要把它改成windows系统服务,让系统替你自动跑起来。今天总结了一下,第一次写,供大家一起分享,望各位朋友多多指导。 我用的是rktools.exe 工具,找到里...
  • liang2980878
  • liang2980878
  • 2015年12月25日 14:48
  • 3593
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VC实现系统热键激活后台服务程序
举报原因:
原因补充:

(最多只允许输入30个字)