爲Windows 7的winsxs文件夾瘦身,慎重。

由於是轉載,該方法在我的win7上不能運行,希望慎重借鑑,還有待研究!!!!!

剛使用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? 控件。如果下載該控件,它將替換機器上原有的任何版本的控件。如果機器上的某個應用程序恰好使用該控件,則很可能也會停止工作。

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

這些問題的原因是應用程序不同組件的版本信息沒有由系統記錄或加強。而且,系統爲某個應用程序所做的改變會影響機器上的所有應用程序-------現在建立完全從變化中隔離出來的應用程序並不容易。 

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

.NET框架與DLL Hell問題:發佈和安裝

現在安裝應用程序是多步過程。一般,安裝一個應用程序包括複製許多軟件組件到磁盤,和在系統中進行一系列描述那些組件的註冊項。 

註冊表中的項和磁盤上文件的分隔使複製應用程序和卸載他們非常困難。而且,在註冊表中完全描述某個 COM 類所需的許多項之間關係非常鬆散。這些項常常包括聯合類、接口、類型庫和 DCOM app ID 的項,不涉及任何放在註冊表文檔擴展或組件類別的項。要時常手工保持這些項的同步。

最後,需要該註冊足跡激活任何 COM 類。這極大地複雜了發佈分佈式應用程序的過程,因爲必須到每個客戶端的機器進行適當的註冊項。

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

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

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

***

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章