自制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,如需转载请自行联系原作者

相关文章
|
1月前
|
Linux Shell Windows
通过Linux挂载Windows端NFS服务实现板端Linux传输文件到PC
通过Linux挂载Windows端NFS服务实现板端Linux传输文件到PC
|
1月前
|
存储 安全 数据安全/隐私保护
Windows部署WebDAV服务并映射到本地盘符实现公网访问本地存储文件
Windows部署WebDAV服务并映射到本地盘符实现公网访问本地存储文件
270 0
|
2月前
|
Java Unix 应用服务中间件
使用java service wrapper把windows flume做成服务
使用java service wrapper把windows flume做成服务
|
2月前
|
Windows
修改Windows服务的配置
修改Windows服务的配置
|
3月前
|
Arthas 监控 Java
Arthas 可以用于监控和诊断在 Windows 系统下部署的 Tomcat 服务
Arthas 可以用于监控和诊断在 Windows 系统下部署的 Tomcat 服务
175 2
|
27天前
|
Shell Windows
Windows服务器 开机自启动服务
Windows服务器 开机自启动服务
14 0
|
4月前
|
网络协议 安全 文件存储
Windows本地搭建WebDAV服务并使用内网穿透远程访问【无公网IP】
Windows本地搭建WebDAV服务并使用内网穿透远程访问【无公网IP】
|
4月前
|
监控 Linux 定位技术
Linux【环境部署 01】NTP时间服务器搭建及Linux+Windows客户端使用(一篇学会使用NTP服务)
Linux【环境部署 01】NTP时间服务器搭建及Linux+Windows客户端使用(一篇学会使用NTP服务)
674 0
|
5天前
|
网络协议 安全 测试技术
Windows安装禅道系统结合Cpolar实现公网访问内网BUG管理服务
Windows安装禅道系统结合Cpolar实现公网访问内网BUG管理服务
|
4月前
|
SQL 关系型数据库 MySQL
Trinitycore学习之windows上用cmake生成vs项目并尝试在windows上启动服务
Trinitycore学习之windows上用cmake生成vs项目并尝试在windows上启动服务
52 0