Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 5767|回复: 0

[默认分类] 清理winsxs的小工具

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-11 16:06:30 | 显示全部楼层 |阅读模式
    因为磁盘空间不够了,所以想起来清理一下系统垃圾文件,主要目标就是臭名昭著的winsxs目录。这个winsxs就是微软为了解决“dll hell”问题,结果是好比在windows系统里安置了一个毫无节制不断增大的“肿瘤”。听说微软研究院现在在研究这个问题,不过我想我的硬盘空间不够大,等不到这个补丁出来的时候,所以只好自己动手了。
    winsxs目录下的文件都是系统要用的各种库文件,system32下存放了这些dll的最新的版本,所有老版本的dll都放在winsxs下。所以只要你安装程序或者更新补丁,system32下的文件就会被更新,而同时winsxs就会增加一些旧文件,所以我们的C盘空间就在持续不断地减少,直到磁盘容量不够,被迫重装系统为止,如果你足够幸运,可以直接安装最新的SP的话,或许可以为winsxs节约一点微薄的空间。
    winsxs目录下的不同版本文件都存放在特定命名规则的目录下,比如

    C:\Windows\winsxs>dir msil_microsoft.transactions.bridge.resources*
    驱动器 C 中的卷是 vista
    卷的序列号是 989F-EFF3
    C:\Windows\winsxs 的目录
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6000.16386_zh-cn_1cde5a17d78fb5ec
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6000.16716_zh-cn_1cd75781d79605cf
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6000.20876_zh-cn_060fb27df137fddf
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6001.18000_zh-cn_1cb2dbd3d7e75eb8
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6001.18106_zh-cn_1cb252ffd7e7f8cf
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6001.22221_zh-cn_05e71ebbf18d0b5e
    msil_microsoft.transactions.bridge.resources_b03f5f7f11d50a3a_6.0.6002.18005_zh-cn_1c8e610fd838f2cc
                   0 个文件              0 字节
                   7 个目录  5,382,139,904 可用字节

    这里的各个部分用下划线分割,其中我们关注的是“6.0.6000.16386”部分,它表示旧文件的版本号,之前则是唯一文件标识,之后是语言,最后部分是散列值(防止名字冲突)。
    本工具的设计思想就是删除所有的旧文件。所有满足如下全部条件的目录都会被移动到C:\Windows\winsxs_del目录中。

    存在比自身更新的版本
    本身不是最新版本

    运行工具前的C盘剩余空间:

          所列文件总数:
                4473 个文件  3,336,376,627 字节
                7655 个目录    326,840,320 可用字节
    C:\Windows\winsxs_del>

      
    运行工具并且执行命令

    for /d %v in (%SystemRoot%\winsxs_del\*.*) do rd /s /q %v

    删除所有可以删除的无用文件之后的剩余空间:

          所列文件总数:
                  52 个文件      7,555,048 字节
                 131 个目录  5,383,979,008 可用字节
    C:\Windows\winsxs_del>

      
    工具源代码如下:请保存为winsxs_clear.bat即可。所有不再需要的文件会移动到c:\windows\winsxs_del目录中,可以直接进行删除。
    执行时候,务必请使用“管理员”权限。



      1

    @echo
      
    off


      2

    rem
      获取windows版本


      3

    set
      move_dir
    =
    %SystemRoot%
    \
    winsxs_del

      4

    if
      
    not
      
    exist
      %move_dir%
    \
    nul
    md
      %move_dir%

      5

    set
      winver
    =
    none

      6

    FOR
      
    /
    F
    "
    eol=; tokens=4* delims=]
    "
      %%i in
    (
    "
    ver
    "
    )
      
    do
      
    set
      winver
    =
    %%i

      7

    if
      
    "
    %winver%
    "
      
    ==
      
    "
    none
    "
      
    goto
      enover

      8

    echo
      windows version is %winver%
    ,
      ready to list winsxs
    dir
    .


      9

    if
      
    not
      
    exist
      %SystemRoot%
    \
    winsxs
    \
    nul
    goto
      enosxs

    10


    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
    "
      
    >
      nul

    18

    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-generated

    27

    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
    "
      
    ==
      
    "
    <DIR>
    "
      
    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
    rem
      set 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目录中。如果出现程序无法运行的情况,请手工移动回去即可。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-20 16:17 , Processed in 0.466648 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表