在运行时,去掉当前桌面很简单,SystemParametersInfo( SPI_SETDESKWALLPAPER, 0, "", SPIF_SENDCHANGE );对于任何用户和程序都是适用的,对于Win32服务程序也不例外。
但对于一般的Win32 App只要发送SystemParametersInfo( SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE);就能够恢复会当前的桌面,但对于Win32服务程序就不一定适用了。
原因主要是桌面是存在于HKCU/Control Panel/desktop/Wallpaper下面的,而一般的Win32服务程序都是以Local System的用户来执行的,在恢复的时候它查找的就是HKU/.Default,而不是当前登录的用户。对于.Default用户一般都不存在Wallpaper这个键值,所以对于恢复的调用,一般情况LastError都是2,提示找不到桌面文件。
研究了一下ultraVNC的源码,发现它利用了一个外部程序Service Helper来给Win32服务发送消息,以获取当前登录用户的AccessToken,最后切换到当前登录用户来进行桌面恢复的。其实这个Service Helper程序,只是放在HKLM或者HKCU/Software/Microsoft/Windows/Run/"Winvnc.exe -serivcehelper"。在Winvnc的Win32服务程序运行的时候先要在系统中登记一个消息“WinVNC.ServiceHelper.Message”,用户登录的时候,这个Service Helper程序开始运行,就给服务程序的vncMenu发送一个消息,消息的参数就是当前这个Service Helper程序的ProcessId。而在Winvnc的Win32服务程序收到这个消息后,就通过这个进程ID把服务进程取当前登录用户的身份。
当然不一定要使用外部程序来发送消息,因为很多Win32都是Console模式的,没有消息循环。而Winvnc的服务程序是Gui模式的,有窗体来接受外部发送的消息。对于普通的Console模式可以使用其他的进程通信方法,比如共享内存。