原文地址为: 清理winsxs的小工具
因为磁盘空间不够了,所以想起来清理一下系统垃圾文件,主要目标就是臭名昭著的winsxs目录。这个winsxs就是微软为了解决“dll hell”问题,结果是好比在windows系统里安置了一个毫无节制不断增大的“肿瘤”。听说微软研究院现在在研究这个问题,不过我想我的硬盘空间不够大,等不到这个补丁出来的时候,所以只好自己动手了。
winsxs目录下的文件都是系统要用的各种库文件,system32下存放了这些dll的最新的版本,所有老版本的dll都放在winsxs下。所以只要你安装程序或者更新补丁,system32下的文件就会被更新,而同时winsxs就会增加一些旧文件,所以我们的C盘空间就在持续不断地减少,直到磁盘容量不够,被迫重装系统为止,如果你足够幸运,可以直接安装最新的SP的话,或许可以为winsxs节约一点微薄的空间。
winsxs目录下的不同版本文件都存放在特定命名规则的目录下,比如
C:\Windows\winsxs 的目录
这里的各个部分用下划线分割,其中我们关注的是“6.0.6000.16386”部分,它表示旧文件的版本号,之前则是唯一文件标识,之后是语言,最后部分是散列值(防止名字冲突)。
本工具的设计思想就是删除所有的旧文件。所有满足如下全部条件的目录都会被移动到C:\Windows\winsxs_del目录中。
- 存在比自身更新的版本
- 本身不是最新版本
运行工具前的C盘剩余空间:
C:\Windows\winsxs_del>
运行工具并且执行命令
for /d %v in (%SystemRoot%\winsxs_del\*.*) do rd /s /q %v
删除所有可以删除的无用文件之后的剩余空间:
C:\Windows\winsxs_del>
工具源代码如下:请保存为winsxs_clear.bat即可。所有不再需要的文件会移动到c:\windows\winsxs_del目录中,可以直接进行删除。
@echo off 2
rem 获取windows版本 3
set move_dir = %SystemRoot% \ winsxs_del4
if not exist %move_dir% \ nul md %move_dir%5
set winver = none6
FOR / F “ eol=; tokens=4* delims=] “ %%i in ( ‘ ver ‘ ) do set winver = %%i7
if “ %winver% “ == “ none “ goto enover8
echo windows version is %winver% , ready to list winsxs dir . 9
if not exist %SystemRoot% \ winsxs \ nul goto enosxs10

11
set ver_prefix = %winver:~ 0 , – 1 %12
echo list winsxs finished! now ready to clear duplicated files
13
echo dir / ad %SystemRoot% \ winsxs \ *_%ver_prefix%*14

15
if “ %1 “ == “ run-winsxs-generated “ goto :lSkipGen 16
rem 准备生成代码 17
copy / y “ %~f0 “ “ %temp%\%~nx0 “ > nul18
echo rem genereted code here >> “%temp%\%~nx0” 19
echo :ldcdStat1 >> “ %temp%\%~nx0 “ 20
echo set end4 = %%arg:%ver_prefix% = %% >> “ %temp%\%~nx0 “ 21
echo goto ldcdStat2 >> “ %temp%\%~nx0 “ 22
echo :ldcdStat3 >> “ %temp%\%~nx0 “ 23
echo set end4a = %%arg:%winver% = %% >> “ %temp%\%~nx0 “ 24
echo goto ldcdStat4 >> “ %temp%\%~nx0 “ 25
rem notepad “%temp%\%~nx0” 26
“ %temp%\%~nx0 “ run -winsxs-generated27
goto :EOF 28

29
:lSkipGen 30
FOR / F “ eol=; tokens=1-4 delims= “ %%a in ( ‘ dir / ad %SystemRoot% \ winsxs \ *_%ver_prefix%*’ ) do ( 31
if “ %%c “ == “ “
call
:fnDoClear
%%d
32

)
33

34

echo
clear OK!
35

goto
:EOF
36

37

:enover
38

echo
could
not
get windows version
,
abort!
39

goto
:EOF
40

41

:enosxs
42

echo
not
found %SystemRoot%
\
winsxs! maybe no privilege or lower windows!
43

echo
only support windows XP and later!
44

goto
:EOF
45

46

:fnDoClear
47

rem
arg: dir_name
48

FOR
/
F
“
eol=; tokens=1-14 delims=_
“
%%g in
(
“
%1
“
)
do
call
:fnDoClearDir
%1
%%g %%h %%i %%j %%k %%l %%m %%n %%o %%p %%q %%r %%s %%t %%u %%v %%w %%x %%y %%z
49

goto
:EOF
50

51

:fnDoClearDir
52

rem
arg: dir_name dir_parts

53

set
d_name
=
%1
54

rem
检查参数是否匹配 %winver%, 先跳过前两个.同时准备组合新版本匹配名称,nv1存当前版本,nv2存当前的前一个版本
55

set
nv1
=
%2
_
%3
_
56

set
nv2
=
%2
_
%3
_
57

:ldcdCycle
58

if
“
%4
“
==
“”
goto
:EOF
59

rem
检查是否 ver_prefix 开头,如果是则继续检查是否winver,如果不是winver则表示目标存在
60

set
arg
=
%4
61

rem
set line=set end4=%%arg:%ver_prefix%=%%
62
rem%line%
63

goto
ldcdStat1
64

:ldcdStat2
65

if
“
%arg%
“
==
“
%end4%
“
goto
ldcdNext
66

rem
检查是否 winver 开头
67
remset line=set end4a=%%arg:%winver%=%%
68
rem%line%
69

goto
ldcdStat3
70

:ldcdStat4
71

if
not
“
%arg%
“
==
“
%end4a%
“
goto
:EOF
72

rem
至此则为 ver_prefix 开头 且 不等于 winver 的目录名,检查最新版本是否存在,存在则可删除旧的
73

set
newfound
=
false
74

for
/
d %%v in
(
“
%SystemRoot%\winsxs\%nv1%%winver%.*_%5_*
“
)
do
(
75
if
exist
%%v
\
nul
set
newfound
=
true
76

)
77

if
“
%newfound%
“
==
“
true
“
call
:fnDelDir
%d_name%
78

79

goto
:EOF
80

:ldcdNext
81

set
nv2
=
%nv1%
82

set
nv1
=
%nv2%
%4
_
83

shift
84

goto
ldcdCycle
85

86

:fnDelDir
87

rem
arg: dir
88

echo
del
%SystemRoot%
\
winsxs
\
%1
89
takeown /
r
/
f
“
%SystemRoot%\winsxs\%1
“
90
cacls “
%SystemRoot%\winsxs\%1
“
/
t
/
e
/
g everyone
:f
91

move
“
%SystemRoot%\winsxs\%1
“
“
%move_dir%\%1
“
92

goto
:EOF
93

94

代码导读有助于大家理解程序和算法,但是基本的批处理语法就不讲了,有几年编程经验的我想也看得懂。以下是大致几个要注意的地方:
- 代码的开头部分是用ver命令获取系统的版本号,并且存放到%winver%变量中,比如我的ver命令返回就是“Microsoft Windows [版本 6.0.6002]”,为了获取这个“6.0.6002”,所以要做一些处理,另外,%ver_prefix%中存放的是类似“6.0.600”,为了比较旧版本号用途。
- 因为批处理无法实现嵌套嵌入功能,比如我想把从目录中分解出来的6.0.6000.16386和%ver_prefix%进行比较,就无法实现了,只好用代码生成大法来处理,在18~24行就是生成代码,该代码在63行和69行调用。26行负责把控制转移到新生成的文件中执行。
- 因为winsxs目录是有特殊权限的,所以先用takeown命令设置当前用户为拥有者,然后用cacls修改目录权限,最后用move指令将目录转移到winsxs_del目录中。如果出现程序无法运行的情况,请手工移动回去即可。
转载请注明本文地址: 清理winsxs的小工具
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/210811.html原文链接:https://javaforall.net
