原文:http://hi.baidu.com/pwcrab/blog/item/8fce6003ef4396e808fa9394.html
我们的程序运行时需要设置一些环境变量,但是在某客户那里,
用户环境中可扩展值 %SystemRoot% 没有被展开。 调查发现原因如下:
注册表中有两种类型的键:
REG_SZ
REG_EXPAND_SZ
如果上面一种键的值中存在可扩展占位符%xxx%的话是不会被解释的
但是如果下面一种键的值中存在%xxx%的话该部分会被系统解释。
以上的描述可以在相关资料中查到。
系统环境变量存放位置
HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Control/Session Manager/Environment
将TEMP TMP的键类型修改为REG_SZ,值设置为 c:/testProj/service/%SystemRoot%
发现该值无法被展开。所以问题的已查明。
为什么用户系统的存放系统环境变量的健值类型会被修改为REG_SZ(默认的都是REG_EXPAND_SZ型)
,这个原因不明,但是,由相关经历如msn升级导致系统中某个键类型变成REG_SZ
导致我们的软件无法安装。
注册表键类型REG_SZ和REG_EXPAND_SZ引发的BUG(续)--“CurrentControlSet”和“ControlSet00?”
原文: http://hi.baidu.com/pwcrab/blog/item/c52aa39ba6ca6db1c8eaf471.html
这个问题原因查明了,确定修改方案时又遇到了新的问题。
一般机器中,控制系统启动的有三个注册表项,在HKEY_LOCAL_MACHINE/SYSTEM下,存在着 CurrentControlSet、ControlSet001、ControlSet002这三个子键,他们包含的内容似乎一样,而且修改一个其它也 会发生变化,那么到底修改哪一个才是合理的呢。那么就让我们首先了解这三个注册表项吧,下面的内容来自于: bbs.mcafeefans.com.cn/viewthread.php?tid=1482106
一、先了解一下控制系统启动的三个注册表项
在HKEY_LOCAL_MACHINE/SYSTEM下,存在着CurrentControlSet、ControlSet001、 ControlSet002这三个子键,他们是与系统启动有关的三个项,里面记录着操作系统配置的信息,包括了系统控制、驱动、服务等信息。
ControlSet001是系统默认的配置信息,但是为了避免序号混乱,windows启动时会从ControlSet001复制一份副本,作为操作系 统当前的配置信息,也就是CurrentControlSet。那么ControlSet002是什么呢?当操作系统每成功启动一次,都将 CurrentControlSet和ControlSet001中的配置信息复制到ControlSet002中,ControlSet002就成了 “最近一次成功启动的配置信息”,也就是启动时按F8之后,你所看到的选项“最后一次正常启动的配置”。
二、为什么编写规则禁止对HKML下“/SYSTEM/CurrentControlSet/Control/SafeBoot/**”作写入、创建、删除之后,仍然可以在该项下写入、创建、删除键和值呢?
根据为什么水哥的国庆规则根本锁不住安全模式的注册表项帖 中麦粉_幽芸提供的信息可以知道,如果我们编写规则禁止对HKML下“/SYSTEM/**/SafeBoot/**”作写入、创建、删除之后,HKML /SYSTEM/CurrentControlSet/Control/SafeBoot/下就不能写入、创建、删除了,并且出现如下日志:
2007-10-28 8:01:36 已由访问保护规则禁止 LYM/hp C:/WINDOWS/regedit.exe /REGISTRY/MACHINE/SYSTEM/ControlSet001/Control/SafeBoot/新值 #1 用户定义的规则:444 已阻止的操作: 创建
明显的能看出,咖啡禁止操作是对HKML/SYSTEM/ControlSet001/Control/SafeBoot/键而不是对HKML/ SYSTEM/CurrentControlSet/Control/SafeBoot/键的。根据这些信息,结合上面第一点中所说我作如下猜测: ControlSet001是真的系统配置信息,而CurrentControlSet只是ControlSet001的一个镜像。 我们要修改启动配置,实际上修改的是ControlSet001,当我们似乎是在CurrentControlSet下写信息时,实际上首先写的是 ControlSet001,又或者在CurrentControlSet下写入的信息只在内存中先作缓存,然后写入ControlSet001,而实际 并未在CurrentControlSet下写入信息;而后CurrentControlSet作为镜像映射ControlSet001内的信息,只有读取的操作,于是CurrentControlSet被更新了,得到了面向用户的配置信息,因为只有读取,所以也不存在被规则阻挡了。
三、如何解决问题?
当然,上面的只是我的猜测。而现在的实际情况就是,根据幽芸提供的日志,我们清楚看出,当我们在CurrentControlSet下写信息的时候,阻挡 ControlSet001操作的规则报警了,我们在CurrentControlSet下写信息的时候,作了在ControlSet001下写信息这一 操作。
无论你是否认同我的猜测,问题都将以下面的方式得到解决:
编写注册表保护规则,命名为“保护安全模式免被破坏”,包含进程为*,要保护的项是HKLM下的/SYSTEM/ControlSet001/Control/SafeBoot/**,阻止的操作为写入、创建、删除。
然后/SYSTEM/CurrentControlSet/Control/SafeBoot/下的修改将不能实现了。
四、补充
在网上找到的资料,大家请看,关于使用了“最近一次的正确配置”之后会发生的事情:
HKLM/system注册表项中还有一个select的子项,其中有几个整数键,分别是:
“Current”数据项目表示 Windows XP 在这次启动过程中使用的控件组。
“Default”数据项目表示 Windows XP 在下次启动时将使用的控件组,它与这次启动使用的控件组相同。
“LastKnownGood ”数据项目表示您在启动过程中选择“最近一次的正确配置”时 Windows XP 将使用的控件组。
“Failed”数据项表示 Windows XP 在其中保存失败启动产生的数据的控件组。 此控件组在用户第一次调用“最近一次的正确配置”选项之前并不实际存在。
对应上面四个值,系统默认时其顺序是:001、001、002、无;
第一次使用“lastknowngood”后:002、002、003、001
第二次使用“lastknowngood”后:003、003、004、002(之前的备份001被002覆盖掉,001组消失)
第三次使用“lastknowngood”后:004、004、001、003(002被003覆盖,而当004要生成新的“lastknowngood”时,001正好可用,于是001重生,002消失)
当大家使用了“最近一次的正确配置”之后,ControlSet001被认为时错误的配置被封存起来(001记录在在Failed中,不使用了),而用ControlSet002启动,相应生成ControlSet003作为“最近一次的正确配置”,002取代了001的位置,003又取代了002的位置。按上面所说,这些ControlSet会循环使用,最多也就4个,分别为001、002、003、004。
为了改善保护效果,避免因为使用“最近一次的正确配置”之后,保护ControlSet001就不起作用(因为002取代了001的位置了),因此对保护的项作更改,更改成:要保护的项是HKLM下的/SYSTEM/ControlSet00*/Control/SafeBoot/**。这样就可以了。
五、关于ControlSet001、ControlSet002以及CurrentControlSet
下午跟笑笑讨论了很久的问题,关于“CurrentControlSet”和“ControlSet00?”这两个键,究竟他们是怎样的关系呢?为什么更 改ControlSet001的内容和权限,CurrentControlSet就会作同样的修改呢?反之也是这样,为什么呢?
晚上我在微软官网找到了些信息,相信大家会有兴趣的,地址是http://support.microsoft.com/kb/100010/zh-cn。
当然,内容都是英文……那么我对部分重要信息作一下解释。
大家应该会看到这么一段:
引用:
ControlSet001 may be the last control set you booted with, while ControlSet002 could be what is known as the last known good control set, or the control set that last successfully booted Windows NT. The CurrentControlSet subkey is really a pointer to one of the ControlSetXXX keys.
说的是,ControlSet001是你最后 成功启动的控制配置,而ControlSet002就是最后一次正确的控制配置,或者说是最后一次使操作系统成功启动的控制配置。 CurrentControlSet呢,就是一个指向其中一个ControlSetXXX(XXX=001或002或003或004)的一个键(pointer=指向者)。
那么为什么CurrentControlSet写入不被咖啡阻挡就清楚了,下面说说我的理解,不过未必正确,剑荣说的很有参考价值,因为我也不明白他说的是什么,请剑荣解释一下了。
我对“在CurrentControlSet写入不被国庆版默认规则阻挡”的理解:因为我们在CurrentControlSet上的操作,其实其实是指 向ControlSetXXX(根据情况不痛,XXX会不同,原因请参考第四点),在CurrentControlSet上的写入操作,将被指向 ControlSetXXX,在ControlSetXXX写入以后,CurrentControlSet将读取ControlSetXXX的信息,因为 CurrentControlSet是指向ControlSetXXX的,他就好像一个镜像,显示ControlSetXXX里的东西。
那么为什么要设置CurrentControlSet键呢?这么麻烦还要指向。我在http://support.microsoft.com/kb/308559/zh-cn上找到了答案,这次是中文的了。
Windows XP 提供 ControlSet001 的副本,名为 CurrentControlSet,这样,应用程序就不必考虑在启动过程中用几号控件组。