服务操作注册表问题

时间:2021-08-26 05:52:35

一般应用程序可以操作注册表,不会出现上面问题。但是做成Windows服务的形式就会存在很多问题。

问题一:服务无法访问到HKEY_CURRENT_USER中的值。

解决服务一般做成LocalSystem,本地服务,本地服务权限比较高,但本地服务无法访问HKEY_CURRENT_USER中的值,因为它是保存当前用户的信息内容(需要用户登录),本地服务无法访问到需要用户登录的注册表信息。HKEY_CURRENT_USER中的值是一直在变的,登录用户不同,值不同,HKEY_USERS下保存了很多sid,包含用户的sid,这个sid是唯一的,由很多因素决定,HKEY_CURRENT_USER就是HKEY_USERS下当前登录sid的映射。

应用程序可以通过代码方式访问到当前用户的sid,如某个sidS-1-5-21-1993962763-1677128483-682003330-1021,用本地服务访问用户sid不可行,访问到的会是S-1-5-18,获取到的是当前用户服务的sid

//C#应用程序获得当前用户的安全标识符

using System.Security.Principal;
WindowsIdentity  windowsIdentity = WindowsIdentity.GetCurrent();
string userSid = windowsIdentity.User.Value;

问题二:服务实现开机自启动。

解决: 服务实现开机启动,需要设置StartTypeAutomatic,可实现开机自启动,但是如果服务里有获取mac地址,网卡,cpu,硬盘等信息的代码,无法实现开机自启动,查找原因是因为服务依赖获取mac地址的信息等模块是依赖Windows服务WMI Performance Adapter,当这个服务还未启动时,自己做的服务也无法启动。在代码里面添加服务依赖 ,也可以添加多个服务依赖     

this.serviceInstaller1.ServicesDependedOn = new string[]{"WMI Performance Adapter"};

问题三:服务有些电脑的数据读取不到

 解决查找问题原因,写log后发现HKEY_USERS下的值没有找到用户的sid,故访问不到HKEY_CURRENT_USER中的键值。可能用户没有登录

 服务是开机启动,服务启动后,可能用户还没有登录,所有访问不到用户的sid信息。等用户登录后,服务的onstart代码已经执行完毕,所有就造成用户数据读不到。处理方法是待用户登录后再去执行服务的处理代码,之前一直让服务代码while循环执行判断用户已登录,可以判断explorer.exe进程是否开启

            while(!flgUserOn)

            {

                  int n=0;

                  Process[] pros = Process.GetProcesses();

                  for ( n=0; n < pros.Length; n++ )

                  {

                      string name = pros[n].ProcessName;

                      if ( name =="explorer" )

                      {

flgUserOn = true;

 break;

}

                  }     

            }

问题四:服务的安装问题

 有三种方式安装服务,一种是用vs自带的工具,在服务exe文件所在目录敲入命令installutil Service.exe安装服务,installutil /u Service.exe卸载服务,第二种方式是用.NET的安装部署项目来安装程序。第三种方式是用C#的代码来安装、卸载停止、开启服务