• 清理winsxs的小工具


    因为磁盘空间不够了,所以想起来清理一下系统垃圾文件,主要目标就是臭名昭著的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目录中。

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

    运行工具前的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
    2rem 获取windows版本
    3set move_dir=%SystemRoot%\winsxs_del
    4if not exist %move_dir%\nul md %move_dir%
    5set winver=none
    6FOR /F "eol=; tokens=4* delims=] " %%i in ('ver') do set winver=%%i
    7if "%winver%" == "none" goto enover
    8echo windows version is %winver%, ready to list winsxs dir.
    9if not exist %SystemRoot%\winsxs\nul goto enosxs
    10
    11set ver_prefix=%winver:~0,-1%
    12echo list winsxs finished! now ready to clear duplicated files 
    13echo dir /ad %SystemRoot%\winsxs\*_%ver_prefix%*
    14
    15if "%1" == "run-winsxs-generated" goto :lSkipGen
    16rem 准备生成代码
    17copy /y "%~f0" "%temp%\%~nx0" > nul
    18echo rem genereted code here >> "%temp%\%~nx0"
    19echo :ldcdStat1 >> "%temp%\%~nx0"
    20echo set end4=%%arg:%ver_prefix%=%%>> "%temp%\%~nx0"
    21echo goto ldcdStat2 >> "%temp%\%~nx0"
    22echo :ldcdStat3 >> "%temp%\%~nx0"
    23echo set end4a=%%arg:%winver%=%%>> "%temp%\%~nx0"
    24echo goto ldcdStat4 >> "%temp%\%~nx0"
    25rem notepad "%temp%\%~nx0"
    26"%temp%\%~nx0" run-winsxs-generated
    27goto :EOF
    28
    29:lSkipGen
    30FOR /F "eol=; tokens=1-4 delims= " %%a in ('dir /ad %SystemRoot%\winsxs\*_%ver_prefix%*') do (
    31    if "%%c" == "<DIR>" call:fnDoClear %%d
    32)
    33
    34echo clear OK!
    35goto :EOF
    36
    37:enover
    38echo could not get windows version, abort!
    39goto :EOF
    40
    41:enosxs
    42echo not found %SystemRoot%\winsxs! maybe no privilege or lower windows!
    43echo only support windows XP and later!
    44goto :EOF
    45
    46:fnDoClear
    47rem arg: dir_name
    48FOR /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
    49goto :EOF
    50
    51:fnDoClearDir 
    52rem arg: dir_name dir_parts
    53set d_name=%1
    54rem 检查参数是否匹配 %winver%, 先跳过前两个.同时准备组合新版本匹配名称,nv1存当前版本,nv2存当前的前一个版本
    55set nv1=%2_%3_
    56set nv2=%2_%3_
    57:ldcdCycle
    58if "%4" == "" goto :EOF
    59rem 检查是否 ver_prefix 开头,如果是则继续检查是否winver,如果不是winver则表示目标存在
    60set arg=%4
    61rem set line=set end4=%%arg:%ver_prefix%=%%
    62rem %line%
    63goto ldcdStat1
    64:ldcdStat2
    65if "%arg%" == "%end4%" goto ldcdNext
    66rem 检查是否 winver 开头
    67rem set line=set end4a=%%arg:%winver%=%%
    68rem %line%
    69goto ldcdStat3
    70:ldcdStat4
    71if not "%arg%" == "%end4a%" goto :EOF
    72rem 至此则为 ver_prefix 开头 且 不等于 winver 的目录名,检查最新版本是否存在,存在则可删除旧的
    73set newfound=false
    74for /d %%v in ("%SystemRoot%\winsxs\%nv1%%winver%.*_%5_*") do (
    75    if exist %%v\nul set newfound=true
    76)   
    77if "%newfound%" == "true" call:fnDelDir %d_name%
    78
    79goto :EOF
    80:ldcdNext
    81set nv2=%nv1%
    82set nv1=%nv2%%4_
    83shift
    84goto ldcdCycle
    85
    86:fnDelDir
    87rem arg: dir
    88echo del %SystemRoot%\winsxs\%1
    89takeown /r /f "%SystemRoot%\winsxs\%1"
    90cacls "%SystemRoot%\winsxs\%1" /t /e /g everyone:f
    91move "%SystemRoot%\winsxs\%1" "%move_dir%\%1"
    92goto :EOF
    93
    94

    代码导读有助于大家理解程序和算法,但是基本的批处理语法就不讲了,有几年编程经验的我想也看得懂。以下是大致几个要注意的地方:

    1. 代码的开头部分是用ver命令获取系统的版本号,并且存放到%winver%变量中,比如我的ver命令返回就是“Microsoft Windows [版本 6.0.6002]”,为了获取这个“6.0.6002”,所以要做一些处理,另外,%ver_prefix%中存放的是类似“6.0.600”,为了比较旧版本号用途。
    2. 因为批处理无法实现嵌套嵌入功能,比如我想把从目录中分解出来的6.0.6000.16386和%ver_prefix%进行比较,就无法实现了,只好用代码生成大法来处理,在18~24行就是生成代码,该代码在63行和69行调用。26行负责把控制转移到新生成的文件中执行。
    3. 因为winsxs目录是有特殊权限的,所以先用takeown命令设置当前用户为拥有者,然后用cacls修改目录权限,最后用move指令将目录转移到winsxs_del目录中。如果出现程序无法运行的情况,请手工移动回去即可。
  • 相关阅读:
    找工作刷题-------->Java相关
    ElasticSearch--------->批量索引------->推荐方法、注意事项、性能优化
    ElasticSearch--------------------->索引设计--------------------->数据库数据迁移至ES,如何根据tables特点设计ES的index/type/shards数目?
    Oracle------------->PL/SQL---------------->连接oracle数据库
    责任链模式
    程序员必备软件
    反射
    Linux 磁盘扩容
    1.4 java8 LocalDate
    观察者模式
  • 原文地址:https://www.cnblogs.com/BigTall/p/1577091.html
Copyright © 2020-2023  润新知