前言
我要开发一个系统服务,服务的作用是定时检测并关闭其他应用的弹窗,但是开发后却发现,服务在运行是压根获取不到任何窗口。
原因在于
Windows服务一般在Session0里,EXE应用一般在Session1里,Win7及以后的系统将服务与应用程序进行了Session隔离,不允许其进行UI交互,可以考虑穿透Session隔离来启动。
这样就想到另一个方法,把业务写成一个控制台程序,在服务中调用,但是依旧不行
服务中启动的其他应用依旧会在Session0中。
那我们就要想个方法能在Session1中运行的方法。
总的来说有以下注意点
- 服务的Account属性设置为
LocalSystem
,安装服务后的登录身份则为本地系统账户 - 不要把Windows服务的程序放在
C:\Users\Administrator\
目录下运行,不然启动服务的时候会遇到权限问题 - 程序要在Session1中运行
创建Windows服务
创建后在Service1.cs
的设计试图上右键 添加安装程序
之后会出现以下两个
点击1
对应的属性 设置 Account
设置为 LocalSystem
点击2
其中
ServiceName
就是安装后显示的服务名称
支持中文
StartType
是启动的方式默认是手动
这里设置为自动
(Automatic),但是注意就算设置为自动在安装服务后也不会自动启动,只有下次重启电脑时才会自动启动。
如图
服务代码
1 | public partial class Service1 : ServiceBase |
服务安装工具
界面效果
服务安装后我们可以通过下面的命令打开服务面板
1 | services.msc |
窗口对应的代码
1 | public partial class MainWindow : Window |
服务操作工具类
1 | using System; |
Session1中运行
我们之前运行是这样的
但是这种方法会在所在的Session中运行,所以这里是不行的。
1 | string exeFile = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CloseWPSPopWin.exe"); |
方法1
调用方式
1 | WinAPIInterop.CreateProcess(exeFile); |
工具类
1 | public class WinAPIInterop |
方法2
调用方式
1 | ApplicationLoader.PROCESS_INFORMATION procInfo; |
工具类
1 | /// <summary> |
控制台程序禁止弹窗
把输出类型 改为 Windows应用程序