自制Windows 7 注册表键值修改服务(Service)

简介:

 首先说说为什么要写这么一个服务。由于电脑要在公司域中使用,所以不可避免的会继承域中的组策略配置。域中95% 的计算机是XP系统,部分组策略对于Windows 7 系统来说有些多余而且带来很多麻烦。

问题一、清除虚拟内存策略

     清除虚拟内存策略(Clear virtual memory pagefile)可以在一定程度上降低域中计算机病毒的传播。但问题是如果启动这个策略也会降低Windows 关机速度(3~5分钟),对于关机速度奇快(13~16秒)的Windows 7 系统来说简直是一个沉重的打击。

GroupPolicy

     修改这个组策略只需将[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management] 中的ClearPageFileAtShutdown 设为0x00000000 即可。

Registry

问题二、系统更新策略

     在域中通过组策略可以使计算机通过WSUS 进行补丁更新,虽然是针对XP 系统设置的,但它却完全破坏了Windows 7 系统本身的更新机制,详情请参考《Windows Update Error: 80244019》。解决这个问题的办法只需将注册表中[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate] 完全删除。

解决方法

     由此可见解决上面两个问题都可以通过修改注册表来实现,当然有人会说也可以通过修改域组策略来达到不在某一个域用户主机上应用组策略的效果,但这个方法还是不建议使用。起初写了一个Reg 文件运行一下就将注册表更新了,但总这么做也很麻烦。所以就想到创建一个服务让它在后台运行并修改注册表内容。

Windows Registry Editor Version 5.00

[-HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"ClearPageFileAtShutdown"=dword:00000000

     创建一个Windows Service 项目,新建RegValueSet 类,并写入以下代码内容。在类中ChangeKeyValue() 方法用于完成上述注册表修改操作。其中Registry.LocalMachine.DeleteSubKeyTree(updatePath); 将删除系统更新组策略信息,RegSetValueEx(hKey, keyName, 0, RegistryValueKind.DWord, keyVal, 4); 会将ClearPageFileAtShutdown 键值修改为0。

Service

     开始我尝试通过RegNotifyChangeKeyValue 方法监测SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management 下的键值是否被域组策略修改,如果被修改了便会执行RegSetValueEx 方法,但这种方式在服务中似乎行不通(启动服务时它会一直处于监听状态)。经测试发现其实只需在开/关机时进行ChangeKeyValue() 操作即可,所以便将代码改为以下方式。

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace RegMonitor
{
    class RegValueSet
    {
        private static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
        private static UIntPtr hKey;
        private const int keyRights = 0xF003F; //KEY_ALL_ACCESS (0xF003F)
        
  
   private const 
   UInt32 INFINITE = 0xFFFFFFFF;
  
        
  
   private const 
   UInt32 WAIT_FAILED = 0xFFFFFFFF;
  

        public static void ChangeKeyValue()
        {
            string clrPath = @"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management";
            string updatePath = @"SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate";
            string keyName = "ClearPageFileAtShutdown";
            
            //Delete Windows Update Settings
            int vOpen = RegOpenKeyEx(HKEY_LOCAL_MACHINE, updatePath, 0, keyRights, out hKey);
            if (vOpen == 0)
            {
                Registry.LocalMachine.DeleteSubKeyTree(updatePath);
            }
            
            //Change Clear Page File Value
            RegOpenKeyEx(HKEY_LOCAL_MACHINE, clrPath, 0, keyRights, out hKey);
            
  
   IntPtr hEvent = CreateEvent(
   IntPtr.Zero, 
   true, 
   false, 
   null);

              
  
   RegNotifyChangeKeyValue(hKey, 
   true, 4, hEvent, 
   true);

              
  
   while (WaitForSingleObject(hEvent, INFINITE) != WAIT_FAILED)
  
            
  
   {
  
                RegistryKey key = Registry.LocalMachine.OpenSubKey(clrPath);
                int val = (int)key.GetValue(keyName);
                if (val != 0)
                {
                    IntPtr keyVal = Marshal.AllocHGlobal(4);
                    Marshal.WriteInt32(keyVal, 0, 0);
                    RegSetValueEx(hKey, keyName, 0, RegistryValueKind.DWord, keyVal, 4);
                    key.Close();
                }
                RegCloseKey(hKey);
            
  
   }
  
        }

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int RegOpenKeyEx(
            UIntPtr hKey,
            string subKey,
            int ulOptions,
            int samDesired,
            out UIntPtr hkResult);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern int RegSetValueEx(
            UIntPtr hKey,
            [MarshalAs(UnmanagedType.LPStr)] string lpValueName,
            int Reserved,
            RegistryValueKind dwType,
            IntPtr lpData,
            int cbData);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern int RegCloseKey(
            UIntPtr hKey);

        
  
   [
   DllImport(
   "kernel32.dll")]
  
        
  
   public static extern 
   IntPtr CreateEvent(
  
            
  
   IntPtr lpEventAttributes,
  
            
  
   bool bManualReset,
  
            
  
   bool bInitialState,
  
            
  
   string lpName);
  

        
  
   [
   DllImport(
   "advapi32.dll", SetLastError = 
   true)]
  
        
  
   public static extern int RegNotifyChangeKeyValue(
  
            
  
   UIntPtr hKey,
  
            
  
   bool watchSubtree,
  
            
  
   int dwNotifyFilter,
  
            
  
   IntPtr hEvent,
  
            
  
   bool fAsynchronous);

  
        
  
   [
   DllImport(
   "kernel32.dll", SetLastError = 
   true)]

          
  
   static extern 
   UInt32 WaitForSingleObject(

              
  
   IntPtr hHandle,

              
  
   UInt32 dwMilliseconds);

      }
}

     最后在Service 属性中将CanShutdown 和CanStop 设为True,将Service 名称设为RegistryMonitor。并在OnStart(服务启动)、OnStop、OnShutdown(关机) 加入ChangeKeyValue() 方法就可以了,如下代码所示。

ServiceProperties

using System.ServiceProcess;

namespace RegMonitor
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            RegValueSet.ChangeKeyValue();
        }

        protected override void OnShutdown()
        {
            RegValueSet.ChangeKeyValue();
        }

        protected override void OnStop()
        {
            RegValueSet.ChangeKeyValue();
        }
    }
}

     编译项目后安装RegistryMonitor 服务(Installutil),并在Services.msc 中启动RegistryMonitor 服务。至此,就不用再担心组策略的继承问题了。

Build

RegMonitorService

相关参考

1. RegOpenKeyEx Function 
http://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx

2. RegSetValueEx Function 
http://msdn.microsoft.com/en-us/library/ms724923(VS.85).aspx

3. RegistryKey Methods 
http://msdn.microsoft.com/en-US/library/microsoft.win32.registrykey_methods(v=VS.80).aspx

源程序下载





本文转自Gnie博客园博客,原文链接:http://www.cnblogs.com/gnielee/archive/2010/05/21/windows7-services-edit-registry.html,如需转载请自行联系原作者

相关文章
|
12月前
|
开发框架 监控 安全
Windows Defender 导致 Web IIS 服务异常停止排查
某日凌晨IIS服务异常停止,经查为Windows Defender安全补丁KB2267602触发引擎更新,导致系统资源波动,进而引发应用池回收。确认非人为操作,系统无重启。通过分析日志与监控,定位原因为Defender更新后扫描加重负载。解决方案:将IIS及.NET相关路径添加至Defender排除列表,避免业务影响。
1175 116
|
监控 搜索推荐 开发工具
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
4391 2
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
|
Linux iOS开发 MacOS
Gitea Enterprise 23.4.0 (Linux, macOS, Windows) - 本地部署的企业级 Git 服务
Gitea Enterprise 23.4.0 (Linux, macOS, Windows) - 本地部署的企业级 Git 服务
572 0
Gitea Enterprise 23.4.0 (Linux, macOS, Windows) - 本地部署的企业级 Git 服务
|
安全 Windows
【Azure Cloud Service】在Windows系统中抓取网络包 ( 不需要另外安全抓包工具)
通常,在生产环境中,为了保证系统环境的安全和纯粹,是不建议安装其它软件或排查工具(如果可以安装,也是需要走审批流程)。 本文将介绍一种,不用安装Wireshark / tcpdump 等工具,使用Windows系统自带的 netsh trace 命令来获取网络包的步骤
611 32
|
边缘计算 安全 网络安全
|
C# Windows
【Azure App Service】在App Service for Windows上验证能占用的内存最大值
根据以上测验,当使用App Service内存没有达到预期的值,且应用异常日志出现OutOfMemory时,就需要检查Platform的设置是否位64bit。
447 11
|
网络安全 Windows
Windows server 2012R2系统安装远程桌面服务后无法多用户同时登录是什么原因?
【11月更文挑战第15天】本文介绍了在Windows Server 2012 R2中遇到的多用户无法同时登录远程桌面的问题及其解决方法,包括许可模式限制、组策略配置问题、远程桌面服务配置错误以及网络和防火墙问题四个方面的原因分析及对应的解决方案。
2023 4
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
549 9
|
应用服务中间件 Apache Windows
免安装版的Tomcat注册为windows服务
免安装版的Tomcat注册为windows服务
717 3
|
Java 关系型数据库 MySQL
java控制Windows进程,服务管理器项目
本文介绍了如何使用Java的`Runtime`和`Process`类来控制Windows进程,包括执行命令、读取进程输出和错误流以及等待进程完成,并提供了一个简单的服务管理器项目示例。
420 1