標籤:使用 os 檔案 io art for
剛使用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問題進行了簡單的描寫敘述。
***