Board logo

标题: [系统相关] [讨论]环境变量的存储(2011-05-18更新) [打印本页]

作者: qzwqzw    时间: 2011-4-27 21:26     标题: [讨论]环境变量的存储(2011-05-18更新)

05-18修订


05-06修订


4-30修订


因为看了置顶主题“批处理变量表机制的猜测及测试”
http://www.bathome.net/thread-12030-1-1.html
有感于中间讨论的东西太多太杂
很多常识性的概念和论点被反复讨论
大段的测试代码看的让人头晕
又充斥了一堆似是而非甚至是谬误的言论
所以将变量存储的一些细节另发主题
这里是纯理论探讨
代码测试请另开主题

一、MS-DOS下的环境变量
MS-DOS系统太久远了
关于环境变量的处理这里不做过多的讨论
只大概明确两点
1.环境变量空间分为两类:全局和局部
全局环境由系统核心COMMAND.COM独立创建和维护
局部环境由COMMAND载入exe等应用程序时创建
局部环境创建时会复制全局环境的值
环境空间地址写入程序的PSP
但应用程序结束后不会写会全局环境
大多数操作环境的函数都是针对局部环境的
要写入全局环境需要通过特殊手段得到全局环境的起始地址
但是set命令是针对全局环境进行操作的
因为它是command.com的内部命令
它必然有command.com解释执行
所以自然会索引到command.com的环境空间
也就是全局环境空间
通过C盘根目录的config.sys和autoexec.bat文件可以配置MS-DOS的环境变量

2.MSDOS环境变量是按字节存储的
是按ASCII表顺序存储
变量名会统一转换为大写处理
所以不存在大小写的比较问题
COMSPEC例外,因为它在系统启动时指引IO.SYS寻找COMMAND.COM
其形式是“ 【变量名】=【变量值】【字节0】”
读取变量的方式是顺序遍历
之所以没有用二分搜索遍历
是因为那是的变量空间相对较小
变量的使用频率也相对较低
相对于与变量的索引性能而言
顺序遍历简单而够用
写入变量的方式是顺序遍历后插入
也就是说新变量后的变量会顺序后移

二、Windows下的环境变量
到了Windows系统下发生了很多变化

首先,环境空间变成了三级:
1)系统环境空间,存储在注册表 HKLM\System\CurrentControlSet\Control\Session Manager\Environment\
2)用户环境空间,存储在注册表 HKCU\Environment\  和  HKCU\Volatile Environment
3)启动环境空间,存储在文件 系统盘:\AUTOEXEC.BAT

为了兼容性考虑
位于系统盘根目录的autoexec.bat
仍可以预定义Windows的环境变量
为了安全性考虑
系统只解释autoexec.bat中的环境变量设置语句
如set、path、append等
其它语句不予理会

系统启动时应用程序根据自己的需要读取环境变量
然后写入应用程序自己的环境空间
如果某个环境变量在多个环境空间被定义
将按照“系统、启动、用户”的顺序依次读取并设置
最后被设置的值为环境变量的当前值

path变量是一个特例
它是由"系统、用户、启动"三级空间的对应值组合而来的
也就是说当前path=系统path+用户path+启动path
同样的例子还有LibPath 和 Os2LibPath

应用程序的环境空间有继承特性
如果A进程启动了B进程
那么B进程作为A进程的子进程
将缺省集成A进程的环境空间

而MS-DOS的全局环境空间
类似于现在Windows下explorer.exe的环境空间
因为explorer.exe是Windows默认的外壳
很多情况下用户所启动的程序
包括从开始运行输入cmd、点击“命令提示符”或者批处理文件所启动的cmd.exe
都是作为explorer.exe的子进程运行
所以会继承它的环境空间

两类环境变量通常在“控制面板”的“系统属性”中更改
这不仅了修改了注册表中的相对应的键值
也同时修改了explorer.exe自己的环境空间
所以不用重启电脑马上可以在cmd.exe看到这个变化

也可以直接修改注册表中对应子键的键值
但是需要注销当前用户或重启计算机
由userinit.exe进程重新读取到新的变量状态
从而继承到explorer.exe的环境空间中
在新启动的类似cmd.exe的子进程中才能观察到这种变化

若要无需注销而更新环境空间
可以向所有窗口发送一个 WM_SETTINGCHANGE 广播消息
相关的应用程序(资源管理器、任务管理器、控制面板等)会执行更新
代码示例
  1. SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
  2.     (LPARAM) "Environment", SMTO_ABORTIFHUNG,
  3.     5000, &dwReturnValue);
复制代码
另外,在微软发行的Windows XP Service Pack 2 Support Tools(并非SP2)中
附带了一个命令行工具setx.exe
它可以在命令行中直接修改用户变量或者系统变量

其次,因为Windows系统自2000版本开始内部已全面采用Unicode编码
所以Windows的环境变量也是以Unicode形式存储
也就是说无论英文、汉字还是日文都会占用两个字节的空间
这也就解释了用set获取变量的长度或者子串时都是以字符计数
而非以ANSI存储(对于ASCII是单字节,对于GBK是双字节)的字节计数

环境变量的排序规则也从ASCII更新到了Unicode编码排序
只不过因为Windows支持了小写的变量名形式
所以它的排序比较是忽略大小写的
包括全局英文的大小写也被忽略

再次,对于Windows下的COMMAND.COM曾经有过讨论
它仅仅是虚拟机(ntvdm)封装下的cmd.exe的入口程序
当我们启动command.com时
实际上是启动了ntvdm.exe进程
这个ntvdm不仅仅提供了command命令到cmd.exe命令的虚拟通道
也对16位程序所需的内存环境做了虚拟
包括内存中的环境变量
可以通过创建PIF文件(16位DOS程序的快捷方式)定制内存环境(包括变量环境)
也可以修改%winir%\system32下的CONFIG.NT和AUTOEXEC.NT配置默认的虚拟内存环境

NTVDM虚拟环境最主要的变化就是
把双字节的Unicode映射为了单字节的ASCII编码和双字节的本地化编码(GB)
而debug.exe因为程序本身是为16位环境设计
必须运行在NT虚拟机环境下
启动debug.exe则同时会启动ntvdm.exe
所以debug操作的是ntvdm虚拟出的内存环境
所以它所看到的是单字节的环境变量存储

另外,cmd下多了很多特殊的环境变量
如果cmd的命令扩展被启用(默认是启用状态)
有几个动态环境变量可以被引用
每次变量数值被扩展时
这些变量数值都会被动态计算
它们不会出现在 SET 显示的变量列表中
也不存在于cmd的环境空间中
%CD% - 扩展到当前目录字符串。
%__CD__% - 扩展到当前目录字符串。末尾总会附带分隔路径的斜线。
%DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。
%TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。
%RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。
%ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。
%CMDEXTVERSION% - 扩展到当前命令处理器扩展名版本号。
(NT4下是1;2000,XP下是2;Vista,Win7未确认)
%CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。

还有一些动态变量更为特殊
它们占用了环境空间但是却不会出现在set命令的列表中
不过可以用一些不常见的用法看到它的存在 set,
即set后面直接跟一个半角逗号(也可以是分号或者 set "")
在命令输出的最上方会多出类似下面的变量
=::=::\         标识未访问盘符的当前路径
=C:=C:\Documents and Settings\Administrator   标识已访问盘符的当前路径
=ExitCode=00000001      以32位的16进制数标识Exit /b所指定的错误返回码
它使十进制到十六进制数据转换更加快捷
=ExitCodeASCII=00000001      以ASCII表中对应的字符标识Exit /b所指定的错误返回码
指定的返回码必须大于等于32(也就是空格的ASCII码值)它才会被设置
它使ASCII码值转字符更加方便

最后说说setlocal/endlocal
它会将cmd.exe的当前环境空间另选新的内存空间备份一份
直到endlocal把这个备份空间恢复到当前空间并回收内存
嵌套使用setlocal时会将环境空间多次备份
而后endlocal时会从新到旧恢复空间并收回内存
作者: batman    时间: 2011-4-27 22:07

真正的高人,看得我云里雾里,这个可能要慢慢消化了。。。
作者: batman    时间: 2011-4-27 22:15

本帖最后由 batman 于 2011-4-27 22:20 编辑

“所以Windows的环境变量也是以Unicode形式存储”

这点我有疑问,因为cmd中变量+=号+值的最大字节数是8196,也就是说我当我设置名为str的变量时,str=后面可以跟上8192个单字节字符,如果说无论什么字符都占两个字节,那么为什么后面还能跟8192个单字节字符?
作者: qzwqzw    时间: 2011-4-27 22:44

请确认你的信息来源
这条信息应该是错误的
环境变量的最大长度为8192个字符数(而非字节数)
具体可以用代码测试
限于顶楼规定我就不粘贴了
作者: batman    时间: 2011-4-27 22:54

4# qzwqzw
是我搞错了,确实是字符数,8192这个数字也记错了,2的13次方这下不会错了。。。
作者: powerbat    时间: 2011-4-27 22:54

本帖最后由 powerbat 于 2011-4-27 22:55 编辑

http://technet.microsoft.com/en-us/library/bb490954.aspx
The maximum individual environment variable size is 8192bytes.

http://www.bathome.net/viewthrea ... muid=29086#pid21569
已经讨论过,微软的说法中“字节(byte)”是不准确的,实际可以为字符。

“所以Windows的环境变量也是以Unicode形式存储”,难怪如此,虽然字面上单个变量最大长度为8192字节/字符,但存储时占用空间可能为(8192*2)个字节。
作者: neorobin    时间: 2011-4-27 22:55     标题: 感觉有点热哦

本帖最后由 neorobin 于 2011-4-27 23:01 编辑

楼主所述如果可以列出网上资料 (希望有微软的) 来源 (当然是部分难以查找的资料, 我该先自己搜搜学学), 我想看看, 谢谢!
作者: CrLf    时间: 2011-4-27 22:59

很好奇这些结论是怎么证明出来的...
作者: powerbat    时间: 2011-4-27 23:00

还是linux方便,setenv()、getenv() 自由使用
作者: qzwqzw    时间: 2011-4-27 23:16

限于时间仓促
有些特殊存储的环境变量未及表述
比如date、time、random、cmdcmdline、cd等动态变化的状态变量
比如::、=c:、=d:、=e:等无法正常读取和写入的当前路径变量
有空再说吧
作者: hanyeguxing    时间: 2011-4-28 13:40

本帖最后由 hanyeguxing 于 2011-4-28 13:47 编辑

8# zm900612


  父进程 explorer.exe 在新建 cmd.exe 进程的用户空间为其建立了 PEB 之后,还通过 KlInitPeb (在父进程的用户空间执行)对此 PEB 加以进一步的初始化,在此之前已经准备好了 PPB 作为调用参数之一传下来。进程参数块是一个 RTL_USER_PROCESS_PARAMETERS 数据结构,里面带下来的参数中有一个指针 Environment ,指向一个“宽字符 Unicode” 串,这就是各环境变量的定义。

  参数 PPB 实际涉及两块数据。一块是进程参数块本身,这是有固定大小的;另一块的内容是一些环境变量字符串,这些字符串游离在进程参数块外面,并且也没有固定的长度。这里的目的就是要把这两块数据都复制到新建 cmd.exe 进程的用户空间去,并相应地设置好相关数据结构中的指针。为此,程序中首先要确定这些环境变量字符串所占的长度 EnvSize 。

  知道了这些环境变量字符串所占的长度 EnvSize 以后,如果非 0,就要在新建 cmd.exe 进程的用户空间分配相应的区间。这里在调用 NtAllocateVirtualMemory 时的第 2 个参数、即指针 EnvPtr 的值已预先设置为 NULL ,表示对起始地址没有特定的要求;并且第 3 个参数、即要求在所分配起始地址中前导 0 的个数也是 0 ,因此可以分配在任意的部位 (前导 0 的个数实际上大致上给定了一个部位)。对于这样的分配要求,内存管理会在目标空间从低到高扫描,以找到第一个符合大小要求的区间。由于用户空间的起点是 0x10000 ,这又是第一次要求由内存管理自由分配,所以实际分配的位置一定在 0x10000 处。另一方面,由于区间分配的粒度是 64KB ,所以实际分配的一般总是 64KB ,因为很难设想 EnvSize 会大于 64KB 。实际分配的位置和大小则通过参数 EnvPtr 和 EnvSize1 返回。然后通过 NtWriteVirtualMemory 将来自参数 Ppb、或当前进程的环境变量字符串复制到新建 cmd.exe 进程用户空间的这个区间中。

  接着把 PPB 复制过去并对新建进程用户空间 PPB 和 PEB 中的几个成分作出修正,然后 NtReadVirtualMemory 从 PEB 读取其 ImageBaseAddress 字段,并通过参数 ImageBaseAddress 返回目标映像装入用户空间后的起始地址。

  再接着就是创建新进程的第一个线程、堆栈、TEB 等等。。。。。。
作者: cjiabing    时间: 2011-4-28 14:15

我说他们瞎折腾他们又不听,还是兄理顺了点思路,不过要搞清楚还是需要更详细的解释,期待内行!~
作者: batman    时间: 2011-4-28 14:50

12# cjiabing
折腾不好吗?理论不都是折腾出来的。。。

ps:当初牛顿直接把那个苹果吃掉,万有引力定律将会在何方?
作者: CrLf    时间: 2011-4-28 15:13

11# hanyeguxing


这个...惭愧,基本上还是看不懂...
作者: ▄︻┻═┳一    时间: 2011-4-28 16:33

本帖最后由 ▄︻┻═┳一 于 2011-4-28 17:01 编辑

1# qzwqzw


在“系统属性”中更改全局变量和用户变量后
不仅仅了修改了注册表中的相对应的键值
也同时修改了explorer.exe的环境变量
所以如果我们仅仅修改注册表中的环境变量键值
那么需要重新启动explorer.exe才能读取到环境空间中


重启explorer.exe? 何种方式重启,是任务管理器结束 然后 start explorer的方式还是takill 杀explorer 然后 start explorer?

还是 用注销的方式 ?
作者: CrLf    时间: 2011-4-28 16:40

15# ▄︻┻═┳一


用任务管理器关闭与taskkill有区别吗?
作者: ▄︻┻═┳一    时间: 2011-4-28 16:54

16# zm900612


任务管理器 结束进程有两种方式,一种是应用程序 选项框里结束,一种是进程选项框里结束。

应用程序选项框里结束 是安全结束,不同于taskkill 强杀进程 那样结束。
作者: ▄︻┻═┳一    时间: 2011-4-28 16:57

17# ▄︻┻═┳一


上面说反了,进程选项框里结束 是安全结束
作者: ▄︻┻═┳一    时间: 2011-4-28 17:21

1# qzwqzw


1# qzwqzw

因为explorer.exe是Windows默认的外壳
大多数程序都是它的子进程
也自然继承了它的环境空间
所以我们无论从开始》运行中启动cmd
还是直接点击运行cmd.exe或者批处理
都将会成为explorer.exe的子进程
也同时继承它的环境空间


对这些我不甚了解,但我怀疑你的信息来源,

cmd.exe 不同于一般的应用程序,windows的shell 是系统最后一个启动的一个进程。

f8-- 带命令行的安全模式 就证明了 cmd.exe 是独立于 explorer.exe
作者: CrLf    时间: 2011-4-28 17:24

17# ▄︻┻═┳一


原来如此,学习了
作者: hanyeguxing    时间: 2011-4-28 18:26

本帖最后由 hanyeguxing 于 2011-4-28 18:29 编辑

19# ▄︻┻═┳一


对这些我不甚了解,但我怀疑你的信息来源,
cmd.exe 不同于一般的应用程序,windows的shell 是系统最后一个启动的一个进程。
f8-- 带命令行的安全模式 就证明了 cmd.exe 是独立于 explorer.exe

1,恰恰相反,cmd.exe 和一般应用程序没什么不同,都是一个32位GUI程序
2,至于:
因为explorer.exe是Windows默认的外壳
大多数程序都是它的子进程
也自然继承了它的环境空间
所以我们无论从开始》运行中启动cmd
还是直接点击运行cmd.exe或者批处理
都将会成为explorer.exe的子进程
也同时继承它的环境空间

这里说的是 cmd.exe 的一般启动方式,这和其他一般应用程序也一样。但不代表说程序就必须从外壳 explorer 上作为子进程启动, cmd 是这样,其他程序也是这样。
3,“f8-- 带命令行的安全模式 就证明了 cmd.exe 是独立于 explorer.exe”
任何程序,只要愿意,都可以独立于外壳而单独装载运行。打个比方,把外壳关闭了qq程序就进程结束了吗?把外壳关了在任务管理器中就不能启动其他应用程序了吗?

系统经过 Pre-Boot 阶段最后加载 NTLDR 文件,切换实模为保护、ntdetect.com 收集信息、加载内核 ntokrnl.exe 、加载 HAL ;然后 system 初始化内核、创建会话管理子系统;smss.exe 创建用户模式并初始最原始的环境、加载 Win32k.sys 、启动 Csrss.exe 与 Winlogon.exe 进程;Winlogon.exe 启动 Services.exe 进程、Lsass.exe 进程、Userinit.exe 进程;Userinit.exe 进行用户初始化后,然后启动 Explorer.exe ,也是 Userinit.exe 启动的带命令行的安全模式中的 cmd.exe ,最后 Userinit.exe 退出。
看明白环境这一过程中环境的继承了吗?
作者: batman    时间: 2011-4-28 19:47

21# hanyeguxing
以上是gogel的吗?
作者: hanyeguxing    时间: 2011-4-28 19:51

本帖最后由 hanyeguxing 于 2011-4-28 19:52 编辑

22# batman


是说启动部分,还是?http://blog.sina.com.cn/s/blog_51a4af870100ds9h.html
很早以前写的。。。当时是大部分抄微软官方网站的
作者: batman    时间: 2011-4-28 19:52

23# hanyeguxing
只是觉得术语用得实在太专业,很像官方发布。。。
作者: hanyeguxing    时间: 2011-4-28 19:58

因为当时 ntldr 总出问题,所以就在 xp 启动上用了点时间
作者: slore    时间: 2011-4-28 20:53

注册表把SHELL是explorer删除。。。重启看看,或者直接把explorer改名,重启。
启动后打开任务管理器(ctrl+shift+esc),运行新建任务,cmd。

看看环境变量如何。。。。

用procexp可以看到进程树状结构。

刚才直接看了下,任务管理器是属于SYSTEM下面的winlogon,所以在这里运行cmd,不是属于explorer的子空间。
作者: slore    时间: 2011-4-28 20:56

右键任务栏打开的任务管理器是explorer所启动的。。。
作者: slore    时间: 2011-4-28 20:57

环境变量用API
SetEnviromentVaraible。。。随便打的,是环境和变量的英文。。。MSDN有。。。
自己可以想办法跟进去看。。。应该不是explorer去刷新。
作者: qzwqzw    时间: 2011-4-30 18:22     标题: 4-30修订

本帖最后由 qzwqzw 于 2011-4-30 22:28 编辑


作者: ▄︻┻═┳一    时间: 2011-5-6 11:24

在“系统属性”中更改全局变量和用户变量后
不仅仅了修改了注册表中的相对应的键值
也同时修改了explorer.exe的环境变量
所以如果我们仅仅修改注册表中的环境变量键值
那么需要重新启动explorer.exe才能读取到环境空间中



注册表添加环境变量,然后用任务管理器结束掉explorer进程,再重启explorer的方式,

cmd中不能读取新添加的环境变量。


需要注销系统(logoff)或者重启系统才可以在cmd中读取环境变量。

以上在xp系统中测试。
作者: Batcher    时间: 2011-5-6 12:03

30# ▄︻┻═┳一


重启explorer之后,还需要重启cmd
作者: ▄︻┻═┳一    时间: 2011-5-6 12:37

31# Batcher


这个我当然知道,重启exploer后再重启cmd.exe N*N 也 不会读取环境变量。

至少得注销一次系统才可以“刷新”系统环境变量。
作者: qzwqzw    时间: 2011-5-6 17:00

32# ▄︻┻═┳一
我得承认关于explorer.exe环境空间的部分内容
写得是过于随意了些
虽然改过一次
仍然不是很满意

“只是需要重新启动explorer.exe才能刷新到它的环境空间中”
这句话未将问题的本质描述清楚
应用程序的环境空间有继承特性
这句话同样适用于explorer.exe以及其他应用程序
在你使用“任务管理器”结束exploer.exe时
应该知道“任务管理器”的进程位于进程树
System->smss.exe->winlogon.exe->taskmgr.exe
而修改注册表中的环境变量不会对这些进程的环境空间产生影响
那么使用taskmgr.exe启动的explorer.exe自然不会继承到新变量

而注销后重新登录或者系统重启
是由userinit.exe启动的explorer.exe
而userinit.exe的主要作用就是读取计算机和用户配置
包括环境变量
那自然会从注册表中抓取到新的变量
再被它的子进程explorer.exe所继承

我原文中的重启explorer.exe
是在这样的测试条件下成功的
打开cmd.exe
set _newvar=value设置一个新变量
taskkill /im:explorer.exe /f杀掉当前的explorer.exe进程
start explorer.exe启动一个心得explorer.exe进程
这个新进程作为cmd.exe的子进程
自然会继承cmd的环境空间
其中就包括新定义的变量_newvar

不知道这样说你是否清楚了?
作者: qzwqzw    时间: 2011-5-6 17:12

本帖最后由 qzwqzw 于 2011-5-6 17:17 编辑

05-06修订

作者: CrLf    时间: 2011-5-6 17:25

33# qzwqzw


将explorer作为cmd的子进程,这个方法我咋没想到呢...
作者: CrLf    时间: 2011-5-6 17:27

System->smss.exe->winlogon.exe->taskmgr.exe
这条见解很独到,非常深刻,学习了!
作者: ▄︻┻═┳一    时间: 2011-5-6 19:25

33# qzwqzw

谢谢,你很认真。

我只是喜欢严谨
作者: Batcher    时间: 2011-5-6 20:12

32# ▄︻┻═┳一


往注册表里面写一个环境变量,重启explorer和cmd,新的cmd里面无法识别这个环境变量?你的测试环境是?
作者: ▄︻┻═┳一    时间: 2011-5-6 22:19

38# Batcher

我是用xp sp3 如下测试的:

注册表添加 环境变量 test:
cmd中 执行 “reg add HKCU\Environment\ /v test /d 1234567890”

然后任务管理器结束掉explorer.exe,cmd.exe

关掉任务管理器

ctrl+alt+delete 打开任务管理器, 文件》新建任务(运行),输入explorer,

再在运行中输入cmd

在cmd中输入set test
  1. 显示“环境变量 test 没有定义”
复制代码

作者: plp626    时间: 2011-5-16 21:00

1# qzwqzw


很好。。。
作者: temp    时间: 2011-5-16 22:28

没看明白~~~
修改注册表设置我采用.inf文件,执行用
  1. rundll32 setupapi,InstallHinfSection DefaultInstall 132 .\*.inf
复制代码
结束用资源管理器用
  1. taskkill.exe /im explorer.exe /f
复制代码
刷新用
  1. gpupdate /force
复制代码
  1. RunDll32.exe USER32.DLL,UpdatePerUserSystemParameters
复制代码
重新新启动资源管理器
  1. start explorer.exe
复制代码
注册表修改生效 (xpsp2 xpsp3 2003通过)
作者: Batcher    时间: 2011-5-17 01:51

39# ▄︻┻═┳一


不试试41楼的方法?
作者: techon    时间: 2011-5-17 02:21

此文对cmd 环境变量分析总结的比较透彻,谢谢LZ

顺便问下 set,这个是怎么发现的呢? 以前从来没见过


hanyeguxing 斑竹
对NT内核了如指掌啊,佩服
作者: qzwqzw    时间: 2011-5-17 21:07

41# temp
测试了一下
因为没有现成的inf文件
直接regedit修改HKEY_CURRENT_USER\Environment下的已有变量
然后杀进程、刷新、启进程
结果无效!

另外印象中有直接刷新当前Explorer.exe环境空间的命令行
似乎也是用的rundll32
可惜找不到了
作者: caruko    时间: 2011-5-17 22:32

本帖最后由 caruko 于 2011-5-17 22:34 编辑

一般来说,子进程都会继承父进程的环境变量。
start /I 命令也可以放弃继承,使用新环境,也就是初始环境。

有一次使用bat来做open vpn密码验证程序,发现OPENVPN的登陆密码和用户名是以环境变量的形式存在的,这样方便调用外部程序传递一些数据。
当时还担心过它的安全,后来查了一些资料才了解。
作者: CrLf    时间: 2011-5-17 22:38

45# caruko


我都没怎么注意过start的开关,平时用得太少,看来以前忽略了太多很多值得发掘的东西
作者: temp    时间: 2011-5-18 17:17

41# temp
测试了一下
因为没有现成的inf文件
直接regedit修改HKEY_CURRENT_USER\Environment下的已有变量
然后杀进程、刷新、启进程
结果无效!

另外印象中有直接刷新当前Explorer.exe环境空间的命令行
似 ...
qzwqzw 发表于 2011-5-17 21:07

把的注册表文件直接贴上来吧,我把现成测试好的inf格式文件贴上来
作者: applba    时间: 2011-5-18 17:24

“这也就解释了用set获取变量的长度或者子串时都是以字符技术”

最好两个字错了
作者: temp    时间: 2011-5-18 21:45

41# temp
测试了一下
因为没有现成的inf文件
直接regedit修改HKEY_CURRENT_USER\Environment下的已有变量
然后杀进程、刷新、启进程
结果无效!

另外印象中有直接刷新当前Explorer.exe环境空间的命令行
似 ...
qzwqzw 发表于 2011-5-17 21:07

试试这样行不行
  1. @echo off
  2. title=        
  3. :start
  4. set /p NetConf=请输入你选择的操作(1修改;2还原):
  5. if /i "%NetConf%" equ "1" (goto 1) else if /i "%NetConf%" equ "2" (goto 2) else (goto :eof)
  6. :1
  7. echo.
  8. Set HDD=
  9. set /p HDD=完整的路经及文件名[如 d:\temp ]:
  10. if not exist "%HDD%" (md "%HDD%")
  11. (echo [Version]
  12. echo Signature="$CHICAGO$"
  13. echo.
  14. echo [DefaultInstall]
  15. echo AddReg=AddReg
  16. echo [AddReg]
  17. echo hkcu,"Environment","TEMP",0x20000,"%HDD%"
  18. echo hkcu,"Environment","TMP",0x20000,"%HDD%"
  19. echo [Strings])>>.\Modift.inf
  20. rundll32 setupapi,InstallHinfSection DefaultInstall 132 .\Modift.inf
  21. del /f /s /q .\Modift.inf
  22. taskkill.exe /im explorer.exe /f
  23. RunDll32 USER32,UpdatePerUserSystemParameters
  24. start explorer.exe
  25. exit
  26. :2
  27. (echo [Version]
  28. echo Signature="$CHICAGO$"
  29. echo.
  30. echo [DefaultInstall]
  31. echo AddReg=AddReg
  32. echo [AddReg]
  33. echo hkcu,"Environment","TEMP",0x20000,"%%USERPROFILE%%\Local Settings\Temp"
  34. echo hkcu,"Environment","TMP",0x20000,"%%USERPROFILE%%\Local Settings\Temp"
  35. echo [Strings])>Modift.inf
  36. rundll32 setupapi,InstallHinfSection DefaultInstall 132 .\Modift.inf
  37. del /f /s /q .\Modift.inf
  38. taskkill.exe /im explorer.exe /f
  39. RunDll32 USER32,UpdatePerUserSystemParameters
  40. start explorer.exe
  41. exit
复制代码

作者: qzwqzw    时间: 2011-5-19 09:21

49# temp
试了两台PC
均为XP SP2
表现均为注册表更新
而实际cmd未更新
倒是批处理中HDD变量
因为没有setlocal
结果被explorer继承
成为伪全局变量
[attach]3817[/attach]
作者: temp    时间: 2011-5-19 12:39

50# qzwqzw
会不会是选择的键无效,如修改"我的文档"下述位置是无效的
  1. HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
复制代码

作者: qzwqzw    时间: 2011-5-19 14:28

这个你有测试成功吗?
作者: LJY4.0    时间: 2022-6-12 14:04

应该是task后start
作者: LJY4.0    时间: 2022-6-12 16:11

回复 46# CrLf
我只用过/min
作者: 拒绝访问    时间: 2022-6-12 16:27

基本看不懂




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2