應用程式/解決方案‎ > ‎雜記‎ > ‎專題‎ > ‎應用‎ > ‎

於NTFS下善用VHD虛擬硬碟


從Windows 95開始有Virtual PC就已經有VHD的存在, 這種以一個檔案充當一顆硬碟的功能越用越廣泛...
最初當然是設計給虛擬PC當硬碟用的, 後來支援讀取或處理的工具越來越多, 應用的想法和點子就越發無奇不有了~
於Windows 7開始, 視窗系統的磁碟管理介面就已經直接支援虛擬磁碟的使用功能選單,
而命令列處理的指令則是擴充在 diskpart 裏面以 VDISK 和原本的 DISK 來區別處理焦點,
(雖然Windows XP就已經就有提供相同的 diskpart 功能, 但尚未支援 VDISK 的管理)
這裡不打算作正規的介紹, 網路到處都有可以自己去找

一般來說, 大家都知道Windows裏的一個磁碟分割空間通常就是以英文字母 C: D: E: ... Z: 的方式作為磁碟標號來操作,
而NTFS下則還可能以一個空的資料夾來作為磁碟標號進行操作, 這樣的功能讓磁碟標號不受限於 26個英文字母,
在還不能有這樣的應用方式時, 常常資料受限於磁碟空間不足而安置於不同硬碟, 容易於管理上造成麻煩,
特別是不同系統上的空間分配方式和磁碟標號的規劃不同, 而一些程式或指令都要改設定才能與之配合,
而若能以資料夾就是一個磁碟標號來處理後, 很多顆硬碟可以變成好像是在同一顆硬碟上使用,
這樣可以讓應用上的規劃都可以全部以相對路徑的方式來設計, 而不會因系統用的CDE...Z磁碟不同而每每需要調整,
舉例來說, 假如作業系統在 C: 槽, 尚有多顆硬碟多個磁碟分割, 都能以此方式變成在 C: 槽裏面一起使用,
倘原本有 C: D: E: , 可以規劃變成 C:\HDD-1 就是原本的 C: , C:\HDD-2 則是 D: , C:\HDD-3 則是 E: ,
不同的系統即使連開機槽也不是 C: 也沒有 D: 和 E:, 但最後都能用這種方式重新規劃成有一模一樣的 C:\HDD-1,2,3
同樣的, 以VHD產生的虛擬磁碟(VDISK)也是能以這種方式來被應用

RamDisk也是現在非常普遍的應用, 這是以Ram虛擬成一個磁碟的方式, 充分享用Ram的速度快感並節約實體硬碟的耗損,
以某P牌為例, 虛擬磁碟的類型分為 SCSI 與 Direct-IO 方式, 前者是仿真磁碟可以於磁碟管理中進行設定,
後者則是RamDisk裝置, 驅動方式與一般磁碟不一樣, 當然也無法於磁碟管理中進行設定, 雖然也能格式化成NTFS,
也能設置資料夾作為磁碟標號, 當然也能用來作為VDISK的磁碟標號, 不僅有速度較優, 基本上兩者使用上也幾乎無異,
唯一有個缺點, 在RamDisk裝置上的VHD檔案, 雖然可被順利連結成一個虛擬硬碟使用, 但是想斷開連結時則會失敗,
由於它的絕對路徑對系統而言是一個裝置路徑而不是一個磁碟路徑, 導致不論是磁碟管理還是diskpart在要處理VHD的斷開時,
因為會將原本VHD檔的完整磁碟路徑抓成是 \??\Device... 的表示方式, 而不是磁碟標籤 \??\Volume... 的表示方式, 所以就失敗了~
而本篇想介紹如何善用VHD虛擬硬碟的一些方法, 會有常常需要斷開也會很想將VHD檔放在RamDisk上使用,
這或許是個bug, 有待微軟工程師有天會發現而將之改善, 所以應用上會有相同想法的, 要選用仿真磁碟(通常模擬SCSI),
若是沒有要搭配RamDisk強調速度的話, 後續的善用VHD虛擬硬碟介紹還是實用的, 可以參考

類似的功能另有 symbolic link 對應方式的 NTFS 連接點 概念用法, XP有 junction 工具程式, Vista以後則內建 mklink 指令,
這裡也不作介紹, 上面關鍵字自己上網找, 其功能與此篇所要介紹的善用VHD虛擬硬碟能作搭配, 妙用無窮

首先, 如果都還沒有任何VHD檔可以使用的話當然就是自己動手建立一個, 透過磁碟管理功能介面的方式就不介紹了,
使用 diskpart 命令來操作的話就是得先開啟一個console(命令提示字元)來操作指令, 要注意必需要有管理員權限才能正確執行,
執行 diskpart 後, 可先下 list 看說明, 若有 VDISK 的項目就代表有支援虛擬磁碟的功能,
而這邊說是要善用VHD虛擬硬碟, 代表我們是希望能極簡化的操作, 大量/反覆的經常性使用,
所以若是要建立一個NTFS有啟用壓縮,容量是128MB的VHD虛擬硬碟, 檔案要建立在 Z:\MyDisk.vhd , 也僅分配單一分割來使用全部容量,
而vhd檔案的大小則希望於實際有用到時才動態擴充慢慢變大, 磁碟標籤就固定取名為 "New NTFS"
於 diskpart 中, 需下達以下指令列 ( NOERR 的部分是讓其作為自動化時允許忽略發生的錯誤而繼續執行後續指令 )

CREATE VDISK FILE="Z:\MyDisk.vhd" MAXIMUM=128 TYPE=EXPANDABLE
SELECT VDISK FILE="Z:\MyDisk.vhd"
ATTACH VDISK NOERR
ONLINE DISK NOERR
CREATE PARTITION PRIMARY

如果要將此虛擬磁碟掛載在一個 Z:\MyDisk 的空資料夾(須先建立好)下使用, 還需下達以下指令列

SELECT PARTITION=1
ASSIGN MOUNT="Z:\MyDisk" NOERR
REM - 因為是新建立的硬碟, 開始使用前要先進行格式化, 依需求方式以下列指令進行格式化
FORMAT FS=NTFS LABEL="New NTFS" QUICK COMPRESS

然後退出 diskpart 時則要下達結束指令 (自動化程序時可以省略)

EXIT

diskpart的語法說明

Microsoft DiskPart 語法:
        diskpart [/s <script>] [/?]

        /s <script> - 使用一個 DiskPart 設定檔。
        /?          - 顯示此說明畫面。



也就是我們可以把前述的9行指令存成一個txt檔, 透過 /s 的參數來自動化

檔案 Z:\create.txt 的內容


CREATE VDISK FILE="Z:\MyDisk.vhd" MAXIMUM=128 TYPE=EXPANDABLE
SELECT VDISK FILE="Z:\MyDisk.vhd"
ATTACH VDISK NOERR
ONLINE DISK NOERR
CREATE PARTITION PRIMARY
SELECT PARTITION=1
ASSIGN MOUNT="Z:\MyDisk" NOERR
FORMAT FS=NTFS LABEL="New NTFS" QUICK COMPRESS
EXIT


以後只要在 Z:\ 有 create.txt 這個檔案, 於命令提示字元下輸入 diskpart 指令如下

diskpart /s Z:\create.txt

在 Z:\ 中, 就會建立一個空的NTFS虛擬磁碟檔案 MyDisk.vhd
並且掛載在 Z:\MyDisk 資料夾下使用 (PS: 同前面說明, 空資料夾 Z:\MyDisk 要先建立好)
之後儲存任何資料進 Z:\MyDisk 都跟平時使用沒甚麼不同, 但實際上所有內容則是存放在 MyDisk.vhd 這個虛擬硬碟檔案中

若是要解除 Z:\MyDisk 的掛載, diskpart 需以下指令操作

SELECT VDISK FILE="Z:\MyDisk.vhd"
SELECT PARTITION=1
REMOVE MOUNT="Z:\MyDisk" NOERR
EXIT

若是還要完全斷開系統磁碟管理與虛擬磁碟檔案間的連結關係則尚須添加步驟, 可存成文字檔 detach.txt

Z:\detach.txt 的內容


SELECT VDISK FILE="Z:\MyDisk.vhd"
SELECT PARTITION=1
REMOVE MOUNT="Z:\MyDisk" NOERR
OFFLINE DISK NOERR
DETACH VDISK NOERR
EXIT


解除掛載並斷開vhd檔連結就能簡化成於命令提示字元下輸入 diskpart 指令如下

diskpart /s Z:\detach.txt

解除掛載後會發現 Z:\MyDisk 仍是一個空的資料夾,
而 MyDisk.vhd 則會因為先前存入的資料量而檔案變大...

經過上面的說明, 在概念上應該已經對diskpart與VDISK有所感覺, 先不深入其他操作的方式,
先想想如果要建立很多不同的VDISK方便自動化上的應用, 好似就得要先建立很多相關的script文件檔來搭配使用,
由於diskpart對於vhd檔與磁碟標號的資料夾指定, 都要求要完整的路徑來表示,
所以一旦想存放的位置不一樣或想要更動(vhd檔或掛載用的資料夾), 那麼所有script都要重新修改或另外準備...
這感覺好像沒有很乾淨好用, 所以換一個方向來來想, 設計一個輸出操作命令內容的程式透過stdio/pipe來進行如何?
那程式就叫作 vhd_diskpart.exe , 定義好功能後, 如會寫批次檔的人也能用一個bat檔就能完成此程式的相關功能,
但這裏不是要介紹的批次檔怎麼寫, 而是要來看看經過程式創意後操作的方式如何簡化,
例如前面建立並掛載的動作變成於命令提示字元下輸入以下指令行

vhd_diskpart N128/Z:\MyDisk.vhd/Z:\MyDisk

可以看到程式會輸出以下內容, 若資料夾 Z:\MyDisk 不存在的話則程式也會先建立,

CREATE VDISK FILE="Z:\MyDisk.vhd" MAXIMUM=128 TYPE=EXPANDABLE
SELECT VDISK FILE="Z:\MyDisk.vhd"
ATTACH VDISK NOERR
ONLINE DISK NOERR
CREATE PARTITION PRIMARY
SELECT PARTITION=1
ASSIGN MOUNT="Z:\MyDisk" NOERR
FORMAT FS=NTFS LABEL="New NTFS" QUICK COMPRESS
EXIT

如果要讓 diskpart 依此輸出執行, 則是於命令提示字元下輸入以下指令行(最後面加上 | diskpart 代表把輸出轉給diskpart)

vhd_diskpart N128/Z:\MyDisk.vhd/Z:\MyDisk | diskpart

由於掛載用的資料夾選擇與vhd檔相同路徑中用相同的主檔名, 所以可以省略為

vhd_diskpart N128/Z:\MyDisk.vhd | diskpart

因為副檔名為預設的.vhd所以也可省略, 而工作路徑也在 Z:\ 中的話, 更可省略成

vhd_diskpart N128/MyDisk | diskpart

也就是說若不加 | diskpart 在後面, 則可看程式會輸出怎樣的內容, 而要讓diskpart執行該內容就補上 | diskpart 在最後面即可,
從前面的說明, 如果反應快的應該能發現重點, 就是透過這樣的方式 操作diskpart變成可以有相對路徑概念的用法,
這可以簡化很多操作, 而且在不同的路徑環境下仍能維持相同的操作方式, 經過這樣的設計巧思就方便多了,
為了讓設計程式的自己不會忘記怎麼用, 程式自帶簡單說明, 不帶參數執行就會秀出來提示

隨意寫寫,將就使用吧~


diskpart script util for vhd.   (C) http://ftw.tw

         Ez to MOUNT/DETACH VHD with diskpart command

Usage:
         vhd_diskpart option/vhd_file[/mount_dir] [| diskpart]

 vhd_file  : vhd file for ATTACH/DETACH
 mount_dir : a empty dir for MOUNT/REMOVE, omit to be the same as vhd_file without ext
 option : 'R' 'W' 'M' for MOUNT, 'U' 'D' for DETACH
         'R'ead for MOUNT as READONLY
         'W'rite or 'M'ount for MOUNT as writable
         'U'nmount or 'D'etach for DETACH
         default PARTITION is 1, or change value append the no with option
          as 'M2' & 'U2' work on partition 2 to 'M'ount or 'U'nmount

 option : 'N' 'F' Create & MOUNT, the new vhd_file created with only 1 partition
         'N' Create a new vhd_file with NTFS/Compress format to MOUNT
         'F' Create a new vhd_file with FAT32 format to MOUNT
         default DiskSize 512 MB, or change value append the size by MB with option

Examples:

mapping Y: as C:\VHD\MyDisk.vhd for partition #1 as 'R'eadonly, and 'U'nmount
show script -
         vhd_diskpart "R/C:\VHD\MyDisk.vhd/Y:"
         vhd_diskpart "U/C:\VHD\MyDisk.vhd/Y:"
work with diskpart -
         vhd_diskpart "R/C:\VHD\MyDisk.vhd/Y:" | diskpart
         vhd_diskpart "U/C:\VHD\MyDisk.vhd/Y:" | diskpart

mapping C:\Temp\MyDisk as C:\VHD\MyDisk.vhd for partition #2 for Writable, and 'D'eatch
show script -
         vhd_diskpart "M2/C:\VHD\MyDisk.vhd/C:\Temp\MyDisk"
         vhd_diskpart "D2/C:\VHD\MyDisk.vhd/C:\Temp\MyDisk"
work with diskpart -
         vhd_diskpart "M2/C:\VHD\MyDisk.vhd/C:\Temp\MyDisk" | diskpart
         vhd_diskpart "D2/C:\VHD\MyDisk.vhd/C:\Temp\MyDisk" | diskpart

mapping C:\Temp\MyDisk as C:\Temp\MyDisk.vhd for partition #1 for Writable, and 'D'eatch
show script -
         vhd_diskpart "W1/C:\Temp\MyDisk.vhd"
         vhd_diskpart "U1/C:\Temp\MyDisk.vhd"
work with diskpart -
         vhd_diskpart "M1/C:\Temp\MyDisk.vhd" | diskpart
         vhd_diskpart "D1/C:\Temp\MyDisk.vhd" | diskpart

mapping C:\Temp\MyDisk as C:\Temp\MyDisk.vhd for partition #1 while working in folder C:\Temp
show script -
         vhd_diskpart "W1/MyDisk.vhd"
         vhd_diskpart "U1/MyDisk.vhd"
work with diskpart -
         vhd_diskpart "M1/MyDisk.vhd" | diskpart
         vhd_diskpart "D1/MyDisk.vhd" | diskpart

Create Z:\Temp\MyDisk.vhd using NTFS format and mapping on Z:\Temp\MyDisk, while working in folder Z:\Temp
show script -
         vhd_diskpart "N256/MyDisk.vhd"
         vhd_diskpart "U/MyDisk.vhd"
work with diskpart -
         vhd_diskpart "N256/MyDisk.vhd" | diskpart
         vhd_diskpart "U/MyDisk.vhd" | diskpart


vhd_diskpart 這程式只收一個參數, 程式會依分隔符 '/' 來解析成多個參數,
由於Windows的檔名不允許斜槓符 '/' 的存在, 所以完全不違和,
如果路徑或檔名含空白, 可以把整個參數用雙引號括起來, 例如

vhd_diskpart "R/C:\My Data\VHD files\Ghost_12.0.0.4112(win exec).vhd/Z:\Temp\ghost"

輸出內容為:

SELECT VDISK FILE="C:\My Data\VHD files\Ghost_12.0.0.4112(win exec).vhd"
ATTACH VDISK NOERR READONLY
ONLINE DISK NOERR
SELECT PARTITION=1
ASSIGN MOUNT="Z:\Temp\ghost" NOERR
EXIT

程式的第三個參數 mount_dir
是要用於指定掛載或卸載的磁碟標號(完整的空資料夾路徑)所在, 如果和vhd檔案相同(只是去掉複檔名)則可以省略

第二個參數 vhd_file
則是指要被操作使用的VDISK虛擬磁碟映像檔的完整檔案位置, 如果和工作路徑相同, 可以省略成只須檔名即可,
副檔名如為預設的.vhd就也可省略

第一個參數 option 則有 'R' 'W' 'M' 'U' 'D' 'N' 'F' 等功能, 極簡化想用的常用操作指令,
其中 'N' 和 'F' 都是建立新的vhd檔並且只用單一分割使用全部空間的方式同時掛載起來使用,
這兩個option後面可接一個數字, 代表所要的磁碟大小(以MB為單位) ,
其中 'N' 是格式化成NTFS並啟用壓縮屬性, 'F'則是格式化成FAT32,
倘指定的 vhd_file 已經存在, 程式會以 EXIT 為第一個輸出指令, 即使有pipe給diskpart也不會執行任何動作,
如此避免不小心把已有內容的vhd檔重新格式化而遺失裏面所有內容,

像是程式碼和IDE環境之類的, 往往檔案不大數量很多, 文件壓縮比又高, 就可以選擇用NTFS的壓縮來大大減少浪費磁碟空間,
FAT32則因為沒有安全性描述, 檔案時間精準度低, 雖無壓縮功能, 但在文件數量不是太多到某種數量級的情況下, 通常更有效率又節省空間

若是要操作已存在的vhd檔案, 則可改用 'R' 'W' 'M' ,
其中 'R' 是使用唯讀模式, 這種方式可以讓一個vhd檔被重複連結使用,
由於vhd檔可以是網芳中的檔案, 如有SSD更可以分享出來共用, 很多應用軟體都是可以僅讀或以光碟模式的方式使用的,
例如FireFox瀏覽器的應用程式資料夾是不須要寫入權限的, 其設計時已經將要寫的部分規劃到user空間去了

而option 'W' 和 'M' 則是一模一樣的功能, 會把vhd掛載成可讀寫的方式來使用,
這種可寫入的完整模式下, vhd檔同時只能被一個Windows連結使用,
但可以把掛載起來的資料夾內容分享到網芳供其他系統來使用其中內容與空間

由於一個VDISK可以用多個磁碟標號掛載使用, 因此重複使用 'R' 'W' 'M' 操作指定的vhd檔就能達成所須掛載的目的,
反之若須卸載則是用 option 'U', 而是否唯讀則取決於最初第一次是用 'R' 還是 'W' 'M',
只要還沒用option 'D' 來解除連結就能重複使用 'R' 'W' 'M' 'U' 來操作使用,
因為一個磁碟是可以有多個分割區的, 所以 'R' 'W' 'M' 'U' 也都能隨後帶一個數字來代表要操作的分割區, 分割區1是預設可省略

最後 option 'D' 是用來解除系統與vhd的連結關係, 倘已無掛載任何磁碟標號, 則無須指定第三個 mount_dir 參數
若是僅有掛載一個磁碟標號, 則可以指定第三個 mount_dir 參數, 同時卸載後隨即解除連結,
會比較常用的方式應該都是使用一個磁碟標號一個分割區而已,
所以基本上針對一個vhd檔動態反覆使用的過程大致上就是 'R' 和 'D' 搭配 或是 'W' 和 'D' 搭配而已吧~

簡單的複習option

(1)操作已存在的vhd檔案 (若有明顯的錯誤參數則會以EXIT作為第一個指令輸出,避免diskpart胡作非為)

M - Mount (將vhd檔掛載磁碟標籤如同一顆硬碟來使用)
U - Unmount (卸載磁碟標籤, diskpart的裏的REMOVE)
R - Readonly (與M相同但以唯讀的方式連結vhd檔)
(也就是vhd檔的內容完全不會被異動, 同一vhd檔若第一次用R來掛載, 則任何之後的掛不論使用M或W也都只能唯讀)
W - Writable (與R反義,與M相同功能,算是多餘的選項)
D - Detach 斷開系統與vhd檔的連結, 若只有掛載單一磁碟標籤可以替代U進行卸載後斷開連結, 若掛載多個標籤還是要用U一一卸載
與系統斷開連結後的vhd檔才可以進行之後的檔案操作, 例如改檔名還是移動檔案或刪除

(2)建立新的vhd檔案 (指定的vhd檔名若已存在檔案則會以EXIT作為第一個指令輸出,避免diskpart把已存在的資料格式化消失)

N - NTFS格式, 採動態擴充檔案大小的模式, 固定啟用壓縮屬性將標籤命名為"New NTFS"
F - FAT32格式, 採動態擴充檔案大小的模式, 固定將標籤命名為"New FAT32"

到這裡才準備開始正式的內容「在NTFS下善用VHD虛擬硬碟」
這時後又要聊一下RamDisk, 以P牌為例可以儲存映像檔於開機時載入, 看似很方便但有缺點又很慢,
因為映像檔的方式是以磁碟結構的磁區方式完整保存與還原,
 所以開多大的RamDisk就代表要處理多大的資料量(沒資料的磁區也要處理),
即使裏面只放一點點常用工具, 若RamDisk開很大而使用映像檔的方式就會明顯感受到很慢...
 且若要變更磁碟大小, 原本的映像檔就不能用了
若是單純只讓RamDisk建立的話, 這樣不論開多大容量都是很快就能完成,
可搭配同步用的小功具, 之後再把要放RamDisk的資料複製進去, 那麼僅就實際資料量處理而已, 會更有效率

為了塞一些資料進虛擬磁碟, 將之前文章中的PyWorkPortable.rar轉成一個console自解壓檔PyWorkPortable.exe ,
自解檔的解壓的命令是 PyWorkPortable.exe -x , 會解壓出一個資料夾 PyWorkPortable 裏面是上篇文章的介紹內容,
然後寫了一個批次檔來測試程序動作, 透過裏面所提供的說明可以瞭解實際作了些甚麼,

批次檔 test.bat 的內容



@echo ========== 產生一個新的NTFS虛擬磁碟檔案 PyNTFS.vhd ==========
@echo 建立一個256MB的NTFS虛擬磁碟檔案 tmp.vhd 並且產生資料夾 tmp 掛載此虛擬磁碟
vhd_diskpart N256/tmp |diskpart

@echo 卸載資料夾 tmp 為磁碟標號的虛擬磁碟並與虛擬磁碟檔案 tmp.vhd 完全斷開連結
vhd_diskpart D/tmp |diskpart

@echo 將剛剛產生的 tmp.vhd 改檔名為 PyNTFS.vhd
if exist tmp.vhd ren tmp.vhd PyNTFS.*

@echo ========= 產生一個新的FAT32虛擬磁碟檔案 PyFAT32.vhd =========
vhd_diskpart F256/tmp |diskpart

vhd_diskpart D/tmp |diskpart

if exist tmp.vhd ren tmp.vhd PyFAT32.*

@echo ========= 將前面運作過程中產生的 tmp 資料夾刪除 =========
if exist tmp rd tmp

@echo ========== 判斷若有產生 PyNTFS.vhd 則進行測試 ==========
if exist PyNTFS.vhd call :TestNTFS

@echo ========== 判斷若有產生 PyFAT32.vhd 則進行測試 =========
if exist PyFAT32.vhd call :TestFAT32

@echo ========= 將前面運作過程中產生的 PyWorkPortable 資料夾刪除 =========
if exist PyWorkPortable rd PyWorkPortable

@echo == 所有程序執行結束 ==
GOTO :EOF

rem -----------------------------------------------
:TestNTFS
@echo ===== TestNTFS ===== NTFS格式觀察 =====
@echo 秀一下存放資料前 PyNTFS.vhd 檔案大小
dir PyNTFS.*

@echo 將虛擬磁碟 PyNTFS.vhd 掛載在 PyWorkPortable 資料夾上使用(資料夾名稱是配合壓縮檔內容)
vhd_diskpart M/PyNTFS/PyWorkPortable |diskpart

@echo 解壓縮的檔案訊息過多,不輸出 (自解檔為一個資料夾 PyWorkPortable 全部內容的壓縮)
PyWorkPortable -x >NUL

@echo 卸載資料夾 PyWorkPortable 為磁碟標號的虛擬磁碟並與虛擬磁碟檔案 PyNTFS.vhd 完全斷開連結
vhd_diskpart D/PyNTFS/PyWorkPortable |diskpart

@echo 看看存放資料後 PyNTFS.vhd 檔案變多大
dir PyNTFS.*

@echo TestNTFS結束
GOTO :EOF

rem -----------------------------------------------
:TestFAT32
@echo ===== TestFAT32 ===== FAT32格式觀察 =====
@echo 秀一下存放資料前 PyFAT32.vhd 檔案大小
dir PyFAT32.*

@echo 將虛擬磁碟 PyFAT32.vhd 掛載在 PyWorkPortable 資料夾上使用(資料夾名稱是配合壓縮檔內容)
vhd_diskpart M/PyFAT32/PyWorkPortable |diskpart

@echo 解壓縮的檔案訊息過多,不輸出 (自解檔為一個資料夾 PyWorkPortable 全部內容的壓縮)
PyWorkPortable -x >NUL

@echo 卸載資料夾 PyWorkPortable 為磁碟標號的虛擬磁碟並與虛擬磁碟檔案 PyFAT32.vhd 完全斷開連結
vhd_diskpart D/PyFAT32/PyWorkPortable |diskpart

@echo 看看存放資料後 PyFAT32.vhd 檔案變多大
dir PyFAT32.*

@echo TestFAT32結束
GOTO :EOF



然後在系統中弄個資料夾取名 t , 把 vhd_diskpart.exe 和 PyWorkPortable.exe 還有 test.bat 都放在 t 資料夾裏面,
之後開個管理員權限的命令提示字元, 並切換工作路徑到 t 資料夾中, 最後再輸入 test 看執行過程,
執行過程的視頻, 前段為Win 7執行過程, 後段則是Win 10的相同對照, 也可參考log檔 vhd_diskpart_test_Win7.txt
影片中可以看到產生vhd檔的過程和檔案大小, 過程中可以看到用來掛載虛擬磁碟的資料夾圖示會由資料夾變成硬碟的樣子...
也可以比對不論是剛新建時空的虛擬磁碟檔, 還是放了相同資料量之後, vhd檔的大小都是有壓縮的NTFS比FAT32要來的大10MB,
這是此例之下的情形, 如果放更多的資料有壓縮的NTFS就可能會比FATS32來的省, 不過要放進去的資料都可以有良好的壓縮比才有效果,
如果放的都是壓縮過的資料, 那麼FAT32可能就會總是比NTFS還來得省空間了~

在Win 7之下, 只要有管理員權限, 可於檔案管理員中瀏覽到 t 資料夾, 直接滑鼠右鍵點 test.bat 檔案,
選擇以系統管理員身分執行就能完成所有動作, 無需另開命令提示字元執行, 如果UAC有取消則可雙擊批次檔就能完成執行動作,
但如果是在Win 10之中, 直接點批次檔的方式就行不通了! 這時候就可以拿 RunAsSYSw 出來用,
例如本例中, 如果把 RunAsSYSw.exe 也放到 t 資料夾內, 然後幫 test.bat 拉個捷徑放在方便要點擊的位置,
再把捷徑內容點出來修改, 將原本的目標是 Z:\t\test.bat 改成為 Z:\t\RunAsSYSw.exe test.bat
如此修改後, 這捷徑的用法就如同Win 7直接使用bat檔的方式都一樣用點的就可以了, 而此種捷徑的的方式Win 7當然也可以通用...

跑完 test.bat, 之前文章中的PyWorkPortable, 現在有兩份VHD版, 一個 PyNTFS.vhd 一個是 PyFAT32.vhd, 可隨喜愛留一個用即可,
以後改用VHD檔掛載的方式來用, 如果只是想跑跑例子看看, 可以用唯讀的方式,
例如使用 PyNTFS.vhd 掛載在 PyTest 資料夾, 便是將原本 PyWorkPortable 資料夾看到的內容變成放在 PyTest 資料夾中

vhd_diskpart R/PyNTFS/PyTest |diskpart

如果看看後想自行更動程式碼測試一下, 那麼先用'D'卸載(解除唯讀的開啟模式)後改用'M'或'W'替換'R'成為可寫的模式來用

vhd_diskpart D/PyNTFS/PyTest |diskpart
vhd_diskpart M/PyNTFS/PyTest |diskpart

想另外多掛一個不同名的 PyTst2 資料夾試試, 兩個資料夾 PyTest 和 PyTst2 有一模一樣的內容, 修改任何一個另一個會一起異動

vhd_diskpart M/PyNTFS/PyTst2 |diskpart

試完了想卸掉測試用資料夾並改用正式工作要用的資料夾 PyRelease 來運作

vhd_diskpart U/PyNTFS/PyTest |diskpart
vhd_diskpart U/PyNTFS/PyTst2 |diskpart
vhd_diskpart M/PyNTFS/PyRelease |diskpart

如果最後想完全關閉不使用, 可以同時卸載並斷開連結

vhd_diskpart D/PyNTFS/PyRelease |diskpart

前一動作也可以分開成兩步驟, 卸載後斷開

vhd_diskpart U/PyNTFS/PyRelease |diskpart
vhd_diskpart D/PyNTFS |diskpart

關閉與系統連結後的 PyNTFS.vhd 之後想複製到哪裡備份或使用都可以, 也可以剪下貼上移動到其他要存放的位置

倘若仔細將 vhd_diskpart 每步驟輸出的 script 拿出來觀察, 可能會覺得好像有一些是多餘的指令,
沒關係, 大可用自以為是的方式將之刪除另外設計出來用用, 或如果用 diskpart /s script 的方式曾經發生不明所以的卡關情形,
甚至弄到重新開機才恢復正常, 那麼就改用 vhd_diskpart 輸出的指令串來重新嘗試看看, 那可是為了一些容錯而巧意的安排~

使用VHD虛擬硬碟有很多好處, 例如,
 - 可以把很多檔案封存在虛擬硬碟成一個檔案, 大大簡化實體硬碟的檔案數量與複雜度進而提升效能
 - 動態掛載卸載的方式, 要用時才掛載起來使用, 不用時則卸載這樣裏面的檔案不易受其他軟體或病毒去作更動
 - 複製VM/VPC等虛擬電腦中使用的VHD檔來掛載, 可透過近端網芳的方式和上線狀態中的VM/VPC作熱同步備份(比任何專業備份有效率又符合實際需求),
 - 備份的VHD檔可易於再完整複製到不同主機/異地或雲端,可用於重建/還原一模一樣的VM/VPC,更能替代原本運作中的主機,便於維護且能維持服務不中斷
 - 使用檔案總管複製/刪除很多檔案與資料夾是很沒效率又會消耗系統資源而容易需要重新開機, 若能調整成複製/刪除單一VHD檔則能大大優化
 - 可掛載網芳中的VHD使用, NTFS又可用空資料夾作磁碟標號而不受26個英文字母的限制, 等同可無限擴充主機的硬碟容量(仍受I/O硬體模擬數量的限制)
 - 相同的軟體不同的版本可以安裝在相同位置以VHD掛載的空間中, 視需要隨時切換掛載的VHD而使環境變成使用不同的版本的軟體
 - USB隨身碟較常使用FAT32, 但有些Unicode檔名FAT32無法處理, 那麼可以放個NTFS格式的VHD檔在USB隨身碟裡掛載使用吧
 - 捨不得SSD經常被寫的話可用FAT32或exFAT, 前項USB用FAT32的道理也是為了避免NTFS太多的寫入動作, 改成放VHD檔在SSD中使用吧
 - VHD掛載可以用唯讀模式, 唯讀模式下同一個VHD檔可被重覆掛載, SSD檔讀取的高效率可以透過網路多加使用, 同樣的軟體 網芳之間只需一份
 - 有些軟體或工具有時為了應用方便的關係會重覆放在多處, 如果都是可以唯讀的, 那麼透過唯讀模式的VHD就只需一份被掛載在各個資料夾即可
 - 像Python這種版本眾多又頗有差異的軟體/工具, 檔案數也不少, 裝很多份不小心就跑錯, 若用VHD一一區隔要用時才掛載不用就卸載省事多了...
 - 磁碟重整? 連結開啟狀態的VHD不會被重整, 卸載斷開的VHD則可被重整, 單一VHD檔重整和把一堆檔案放實體被重整自己試試看哪個好?
 - 網芳中的資源常用NET USE連得亂七八糟, 不如改放VHD檔, 可視需求對映在不同主機下所需的不同工作目錄下, 如此乾淨單純好規劃
 - 寫了一堆在C:才能跑的東東, 遇到只有D:的環境怎辦? 重改一番嗎? 不用, 改用VHD就可隨地而安, 到哪都能萬用了!
 - 複製vhd檔掛載使用, 用壞了或只是玩玩, 卸載後就可刪除, 下次複製又是乾淨的初始環境(可將有意義的vhd檔放SSD,要操作時複製到RamDisk使用)
 - 前述動作或類似的行為可以透過像 vhd_diskpart.exe 這樣的工具程式作成批次檔大大簡化操作, 經常性的動態重新組建所需環境不再麻煩
 - ...

暫存... 待續

沒能一鼓作氣寫完... 就懶了... 怠惰心已生, 先打個包 將文章提到的
 vhd_diskpart.exe , PyWorkPortable.exe , RunAsSYSw.exe , test.bat 封裝壓縮
如有興趣先自己研究下去的可以街口轉帳任意金額, 備註留信箱說明索取 vhd_diskpart, 待作業完成就會寄送至所留信箱


ċ
Wei-Xiuang Wang,
2021年1月25日 上午2:42
註解