為Windows 7的winsxs目錄瘦身,謹慎。


剛使用Win7 系統不久,前段時間在清理系統垃圾時發現,win7系統的windows文件夾下的winsxs 文件夾占用空間很大,想清理之,卻提示無權限無法清理。隨即在網上查了個到底,原來winsxs是一個超大的文件倉庫,系統所在分區差點兒全部的系統文件都在那里至少有一個備份。並且隨着系統的使用,winsxs的所占的空間還將不斷的積累壯大,終於將吞噬整個系統分區的磁盤空間。以下附上搜索來的一篇winsxs的具體描寫敘述文摘、winsxs的瘦身方法和一篇關於 DLL Hell問題 的描寫敘述文摘和大家分享:

 

 

winsxs的具體描寫敘述文摘:

***

winsxs的目錄位於Windows根目錄,是一個超大的文件倉庫,系統所在分區差點兒全部的系統文件都在那里至少有一個備份。有興趣的網友最好還是通過搜索功能在winsxs搜一下公用視頻、公用圖片、公用音樂目錄里的文件,你會發現那些精簡系統時已經被刪除了的文件在winsxs里還能夠找到影子。假如系統文件被刪除或者破壞,用命令sfc /scannow就能夠恢復,但假設將winsxs里面的不論什么一個重要的組件刪除,sfc命令就會失效。系統在線更新的過程是舊版本號文件被新版本號的代替,舊文件自己主動備份在winsxs里;卸載補丁的過程是系統新版本號文件被舊版本號的代替,而舊版本號文件的來源正是winsxs。XP也有相似的功能,但XP下備份文件是能夠直接刪除的,Vista和Win7下不行。所以Vista和Win7占用的空間隨着更新增多會越來越大,並且大得驚人。winsxs里的文件非常重要,建議不要刪除,以我長期的實踐經驗,臨時發現僅僅有ManifestCache和Temp兩個目錄里的緩存文件才干夠安全刪除。

特別提醒:網上全部精簡winsxs的方法都有一定的危急性(微軟官方的工具除外),比如“刪除Backup目錄或用空文件代替同名文件”,盡管它叫Backup,但里面絕對不是備份文件而是關系到系統是否能正常更新和正常“打開或關閉Windows功能”的關鍵文件,某些大量被轉載的文章都在誤導人。某軟件提供刪除Windows內置字體,幫助文件的方法,事實上這對於精簡系統是沒有不論什么意義的,字體和幫助文件在winsxs另一個備份,兩個同樣的文件共用一個儲存空間,換句話說,刪除前和刪除后C盤可用空間不變!可是注意,假設你查看文件或者目錄的屬性,他們都會占空間。又如有人提出刪除winsxs里同名文件較低版本號的一個或幾個,這是一個非常好的想法,但問題是有些同名文件的不同版本號都有重要作用,都不能刪除,比如.Net Framework的相關組件。

***

 

winsxs的瘦身方法:

***


清理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文件夾中。
存在比自身更新的版本號
本身不是最新版本號

執行工具前的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文件夾中,能夠直接進行刪除。

執行時候,務必請使用“管理員”權限。
@echo off
rem 獲取windows版本號
set move_dir=%SystemRoot%/winsxs_del
if not exist %move_dir%/nul md %move_dir%
set winver=none
FOR /F "eol=; tokens=4* delims=] " %%i in ('ver') do set winver=%%i
if "%winver%" == "none" goto enover
echo windows version is %winver%, ready to list winsxs dir.
if not exist %SystemRoot%/winsxs/nul goto enosxs

set ver_prefix=%winver:~0,-1%
echo list winsxs finished! now ready to clear duplicated files 
echo dir /ad %SystemRoot%/winsxs/*_%ver_prefix%*

if "%1" == "run-winsxs-generated" goto :lSkipGen
rem 准備生成代碼
copy /y "%~f0" "%temp%/%~nx0" > nul
echo rem genereted code here >> "%temp%/%~nx0"
echo :ldcdStat1 >> "%temp%/%~nx0"
echo set end4=%%arg:%ver_prefix%=%%>> "%temp%/%~nx0"
echo goto ldcdStat2 >> "%temp%/%~nx0"
echo :ldcdStat3 >> "%temp%/%~nx0"
echo set end4a=%%arg:%winver%=%%>> "%temp%/%~nx0"
echo goto ldcdStat4 >> "%temp%/%~nx0"
rem notepad "%temp%/%~nx0"
"%temp%/%~nx0" run-winsxs-generated
goto :EOF

:lSkipGen
FOR /F "eol=; tokens=1-4 delims= " %%a in ('dir /ad %SystemRoot%/winsxs/*_%ver_prefix%*') do (
 if "%%c" == "<DIR>" call:fnDoClear %%d
)

echo clear OK!
goto :EOF

:enover
echo could not get windows version, abort!
goto :EOF

:enosxs
echo not found %SystemRoot%/winsxs! maybe no privilege or lower windows!
echo only support windows XP and later!
goto :EOF

:fnDoClear
rem arg: dir_name
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
goto :EOF

:fnDoClearDir 
rem arg: dir_name dir_parts 
set d_name=%1
rem 檢查參數是否匹配 %winver%, 先跳過前兩個.同一時候准備組合新版本號匹配名稱,nv1存當前版本號,nv2存當前的前一個版本號
set nv1=%2_%3_
set nv2=%2_%3_
:ldcdCycle
if "%4" == "" goto :EOF
rem 檢查是否 ver_prefix 開頭,假設是則繼續檢查是否winver,假設不是winver則表示目標存在
set arg=%4
rem set line=set end4=%%arg:%ver_prefix%=%%
rem %line%
goto ldcdStat1
:ldcdStat2
if "%arg%" == "%end4%" goto ldcdNext
rem 檢查是否 winver 開頭
rem set line=set end4a=%%arg:%winver%=%%
rem %line%
goto ldcdStat3
:ldcdStat4
if not "%arg%" == "%end4a%" goto :EOF
rem 至此則為 ver_prefix 開頭 且 不等於 winver 的文件夾名,檢查最新版本號是否存在,存在則可刪除舊的
set newfound=false
for /d %%v in ("%SystemRoot%/winsxs/%nv1%%winver%.*_%5_*") do (
 if exist %%v/nul set newfound=true
)  
if "%newfound%" == "true" call:fnDelDir %d_name%

goto :EOF
:ldcdNext
set nv2=%nv1%
set nv1=%nv2%%4_
shift
goto ldcdCycle

:fnDelDir
rem arg: dir
echo del %SystemRoot%/winsxs/%1
takeown /r /f "%SystemRoot%/winsxs/%1"
cacls "%SystemRoot%/winsxs/%1" /t /e /g everyone:f
move "%SystemRoot%/winsxs/%1" "%move_dir%/%1"
goto :EOF



代碼導讀有助於大家理解程序和算法,可是主要的批處理語法就不講了,有幾年編程經驗的我想也看得懂。下面是大致幾個要注意的地方:
代碼的開頭部分是用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文件夾中。假設出現程序無法執行的情況,請手工移動回去就可以。

 

***

 

.NET框架解決DLL Hell問題:問題描寫敘述 :

***

從客戶的角度,最常見的版本號問題就是我們所說的 DLL Hell 問題。簡單地講, DLL Hell 是指當多個應用程序試圖共享一個公用組件(如某個動態連接庫(DLL)或某個組件對象模型(COM)類)時所引發的一系列問題。最典型的情況是,某個應用程序將要安裝一個新版本號的共享組件,而該組件與機器上的現有版本號不向后兼容。盡管剛安裝的應用程序執行正常,但原來依賴前一版本號共享組件的應用程序或許已無法再工作。在某些情況下,問題的起因更加難以預料。比方,當用戶瀏覽某些 Web 網站時會同一時候下載某個 Microsoft ActiveX? 控件。假設下載該控件,它將替換機器上原有的不論什么版本號的控件。假設機器上的某個應用程序恰好使用該控件,則非常可能也會停止工作。

在很多情況下,用戶須要非常長時間才會發現應用程序已停止工作。結果往往非常難記起是何時的機器變化影響到了該應用程序。用戶可能會回顧起一周前安裝了一些東西,但安裝與眼下看到的狀態並沒有不論什么明顯的關聯。 更糟的是,如今非常少有診斷工具幫助用戶(或幫助他們的技術支持人員)確定有什么問題。 

這些問題的解決辦法是應用程序不同組件的版本號信息沒有由系統記錄或加強。並且,系統為某個應用程序所做的改變會影響機器上的全部應用程序—如今建立全然從變化中隔離出來的應用程序並不easy。

非常難建立一個隔離應用程序的一個原因是當前執行時環境僅僅同意單獨版本號組件或應用程序的安裝。這個限制意味着組件的編寫者必須以向后兼容的方式編寫他們的代碼,否則當他們安裝新組件的時候會有終止已有應用程序的風險。實際上,假設可能的話,編寫永遠向后兼容的代碼是非常難的。在 .NET 中,side by side 概念是版本號問題的核心。"Side by side" 是在同一台機器上同一時候執行不同版本號的同樣組件的能力。使用支持並列的組件,編程人員不必努力維護嚴格的向后兼容,由於不同的應用程序自由使用某個共享組件的不同版本號。

.NET框架與DLL Hell問題:公布和安裝

如今安裝應用程序是多步過程。一般,安裝一個應用程序包含復制很多軟件組件到磁盤,和在系統中進行一系列描寫敘述那些組件的注冊項。

注冊表中的項和磁盤上文件的分隔使復制應用程序和卸載他們非常困難。並且,在注冊表中全然描寫敘述某個 COM 類所需的很多項之間關系非常松散。這些項經常包含聯合類、接口、類型庫和 DCOM app ID 的項,不涉及不論什么放在注冊表文檔擴展或組件類別的項。要時常手工保持這些項的同步。

最后,須要該注冊足跡激活不論什么 COM 類。這極大地復雜了公布分布式應用程序的過程,由於必須到每一個client的機器進行適當的注冊項。

如今還有一個共同問題是:對一個正在執行的應用程序進行更新是不現實的。這是 Web 應用程序最大的問題,Web 應用程序必須停止工作然后重新啟動動以更新應用程序使用的 COM 類。

這些問題主要由從組件自己分離傳來的組件描寫敘述引起的。換句話說,應用程序不是自描寫敘述的和獨立的。

以上就對須要.NET框架解決的DLL Hell問題進行了簡單的描寫敘述。

 

 

***


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM