C#编写Wix安装的Windows服务发送Toast通知抛出0x80070005错误
解决方案
核心问题说明
Windows Vista及更高版本采用了会话隔离机制,系统服务默认运行在隔离的会话0中,普通用户登录后运行在会话1、2等用户会话中,「允许服务与桌面交互」选项早已废弃,仅为兼容旧系统保留,无法让会话0的服务直接访问归属于用户会话的Toast通知组件,这是你触发E_ACCESSDENIED错误的根本原因。
具体修复步骤
- 修正Wix配置错误
你提供的ServiceInstall标签存在拼写错误,正确标签名为<ServiceInstall>,你少写了字母r写成了<SeviceInstall>,该错误会导致安装时服务注册参数不生效,需优先修正。另外可以直接删除Interactive="yes"配置,该参数现在没有实际作用,反而会触发系统日志警告。 - 调整Toast通知触发逻辑(最推荐方案)
不要在服务进程内直接调用Toast通知API,推荐采用以下更稳定的架构:- 新增一个随用户登录自启的辅助桌面进程,服务通过命名管道、WCF、本地消息队列等进程间通信方式向该桌面进程发送通知指令,由运行在用户会话中的桌面进程调用
ToastContentBuilder弹出通知,该方案兼容性最强,适配所有支持Toast通知的Windows版本。 - 如果你不想新增辅助进程,可在服务内枚举当前活跃的用户会话,获取目标用户的访问令牌,模拟用户身份后再调用通知API,同时需要提前为你的程序注册合法的AppUserModelId(AUMID),注意该方案需要额外处理多用户同时登录的场景。
- 新增一个随用户登录自启的辅助桌面进程,服务通过命名管道、WCF、本地消息队列等进程间通信方式向该桌面进程发送通知指令,由运行在用户会话中的桌面进程调用
- 可选权限补充配置
如果你坚持要在服务内直接调用通知API,可在Wix安装逻辑中新增注册表权限配置,允许LocalSystem账户访问和Toast通知相关的注册表路径,但该方案兼容性极差,不同Windows版本的注册表路径存在差异,非常不推荐在生产环境使用。同时需要确认你使用unpackaged模式的通知API时,已经提前调用了ToastNotificationManagerCompat的相关初始化方法完成权限注册。
内容的提问来源于stack exchange,提问作者Tumblewood
相关产品推荐
相关产品推荐

