最近公司开发一个加密的项目,客户要求在log off以后加密过程不能停止,即数据转换过程必须还要继续。之前的程序是用MFC写的,为了最小化工作量,我做了一些调研,大致找到有两种办法。
1. 将数据转换过程写为service
这是最通用的方法,方法是将数据转换的线程转移到service 中。当需要进行数据转换时,由AP通知service 对需要加解密的目标进行数据转换。
这个方法实现起来改动幅度相对较大,并且要实现进程间的通信,需要学习相应的进程间通信的方法。
2. 使用local system account 来打开该应用程序
1) 使用 psexec 以 local system account 打开
这个方法是在 <Windows Internal> 一书里面看到的,里面是使用 Sysinternal 开发的工具 psexec ,通过命令行可以将任意应用程序以系统账户打开。在 XP 下实验该工具确实可行,但是,这个方法存在一定问题:
1. 如果原有应用程序存在更新进度条等界面工作,那么在 log off 后,程序界面部分会挂掉,具体表现为 log in 后整个界面近乎死掉, cpu 占用率 100% ,但是主管数据转换的线程扔在工作。如果将程序改写为 console 模式的,则不会出现问题。这里初步怀疑是由于 log off 后, windows 消息机制被死锁导致。
2. Vista 之后的系统上会出现问题兼容性问题,通过 psexec 将 notepad 以 local system account 登陆,程序会出现在不一样的一个 session 里面,需要手动切换才能看到,同时 log off 再 log in 后,该 session 不再可见, notepad 被关闭。
2) 使用 Windows API : CreateProcessAsUser
如果不借助诸如 psexec 的外部工具,使用 CreateProcessAsUser 这个 Windows API 也可以自己编程实现以 l ocal system account 来打开该应用程序 。
psexec 里面不知道是否是使用这个 API 来实现的,但是我在网上找到了一个以该 API 实现的软件: Run As System , http://www.qwertylab.com/FreeTools.aspx 。
通过对 RunAsSystem 进行反编译,同时参考网页如下网页:
http://www.codeproject.com/KB/vista-security/VistaSessions.aspx , 该网页的中文翻译在此:
http://blog.csdn.net/xieqidong/archive/2008/09/16/2936771.aspx
了解了程序的大致步骤,下面以 RunAsSystem 讲解如下:
启动一个名为RunAsSystem的windows service
-> 在该service中,查找程序winlogon.exe,并获得该进程的令牌(winlogon.exe就运行在local system account下)
-> 在service中,复制令牌,并调用 CreateProcessAsUser以该令牌来启动我们要打开的应用程序
-> 停止service
之所以要启动service的原因是,在当前用户(Administrator)权限下,没法得到包含复制等权限的winlogon.exe的令牌,所以必须借助service,因为service正是运行在local system account下的。
通过 RunAsSystem 进行 实验,这个方法 仍然存在一定问题:
1. Log off 后界面死掉的问题仍然存在。
2. 在 Vista 后系统上测试,发现虽然不存在上面 psexec 有的兼容性问题,但 log off 后程序仍然退出,并不能达到我们需要的目的。
在实际工作中,可以按照自己的需要来选择,如果只是做 XP 下的控制台程序,可以选择 local system account 这种方法。