Az előzőekben maga a WhoAmI hívása nem volt különösebben problémás, hiszen néhány egyszerű paraméter megadásával vezérelhettük a működését. De mit tehetünk akkor, ha egy parancssori eszköz saját „interpreter-szerűséggel” rendelkezik, azaz nem egyszerű parancssori paraméterátadással tudjuk vezérelni? A DiskPart ilyen eszköz, ha elindítjuk a parancssorból, akkor egy önálló környezetet kapunk, saját prompttal.
Megjegyzés
Az alábbi példákban a diskpart segédprogramot emelt szintű jogosultsággal futó PowerShell ablakban futtattam.
Nézzük itt a help parancsot, mellyel kilistázhatjuk ez elérhető utasításokat.
c:\>diskpart
Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: SOOST-PC
DISKPART> help
Microsoft DiskPart version 6.1.7601
ACTIVE - Mark the selected partition as active.
ADD - Add a mirror to a simple volume.
ASSIGN - Assign a drive letter or mount point to the selected volume.
ATTRIBUTES - Manipulate volume or disk attributes.
ATTACH - Attaches a virtual disk file.
AUTOMOUNT - Enable and disable automatic mounting of basic volumes.
BREAK - Break a mirror set.
CLEAN - Clear the configuration information, or all information, off the
disk.
COMPACT - Attempts to reduce the physical size of the file.
CONVERT - Convert between different disk formats.
CREATE - Create a volume, partition or virtual disk.
DELETE - Delete an object.
DETAIL - Provide details about an object.
DETACH - Detaches a virtual disk file.
EXIT - Exit DiskPart.
EXTEND - Extend a volume.
EXPAND - Expands the maximum size available on a virtual disk.
FILESYSTEMS - Display current and supported file systems on the volume.
FORMAT - Format the volume or partition.
GPT - Assign attributes to the selected GPT partition.
HELP - Display a list of commands.
IMPORT - Import a disk group.
INACTIVE - Mark the selected partition as inactive.
LIST - Display a list of objects.
MERGE - Merges a child disk with its parents.
ONLINE - Online an object that is currently marked as offline.
OFFLINE - Offline an object that is currently marked as online.
RECOVER - Refreshes the state of all disks in the selected pack.
Attempts recovery on disks in the invalid pack, and
resynchronizes mirrored volumes and RAID5 volumes
that have stale plex or parity data.
REM - Does nothing. This is used to comment scripts.
REMOVE - Remove a drive letter or mount point assignment.
REPAIR - Repair a RAID-5 volume with a failed member.
RESCAN - Rescan the computer looking for disks and volumes.
RETAIN - Place a retained partition under a simple volume.
SAN - Display or set the SAN policy for the currently booted OS.
SELECT - Shift the focus to an object.
SETID - Change the partition type.
SHRINK - Reduce the size of the selected volume.
UNIQUEID - Displays or sets the GUID partition table (GPT) identifier or
master boot record (MBR) signature of a disk.
Ha például futtatjuk a List parancsot, akkor – miután ez önmagában még nem teljes parancs – ennek további paraméterlehetőségeit kapjuk meg a képernyőn:
DISKPART> list
Microsoft DiskPart version 6.1.7601
DISK - Display a list of disks. For example, LIST DISK.
PARTITION - Display a list of partitions on the selected disk.
For example, LIST PARTITION.
VOLUME - Display a list of volumes. For example, LIST VOLUME.
VDISK - Displays a list of virtual disks.
Azaz a teljes eredményhez például ezt kell futtatni:
DISKPART> list disk
Disk ### Status Size Free Dyn Gpt
-------- ------------- ------- ------- --- ---
Disk 0 Online 62 GB 0 B
Disk 1 Online 20 GB 19 GB *
Általában a Diskpart használatával akkor jutunk maradandó eredményhez, ha nem csak egy, hanem több utasítást adunk neki sorban. Általánosan elsőként ki kell választani azt az objektumot, amin dolgozni szeretnénk (1. művelet), majd végrehajtjuk a szándékolt tevékenységet ezen az objektumon (2. művelet). Hogyan lehet ezt megtenni? Szerencsére a Diskpart képes csőből felvenni az utasításokat, így kívülről egyszerre több utasítást is tudunk neki átadni, méghozzá úgy, hogy az elsőként átadott parancs hatálya még érvényben marad a második kiadásakor is, és az egész végén ráadásul automatikusan ki is lép a saját futtatási környezetéből. Például:
PS C:\training> "Select disk 0", "detail disk" | diskpart
Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: DC
DISKPART>
Disk 0 is now the selected disk.
DISKPART>
VBOX HARDDISK ATA Device
Disk ID: E4A712E6
Type : SATA
Status : Online
Path : 0
Target : 0
LUN ID : 0
Location Path : PCIROOT(0)#PCI(0D00)#ATA(C00T00L00)
Current Read-only State : No
Read-only : No
Boot Disk : Yes
Pagefile Disk : Yes
Hibernation File Disk : No
Crashdump Disk : Yes
Clustered Disk : No
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
Volume 1 System Rese NTFS Partition 100 MB Healthy System
Volume 2 C NTFS Partition 62 GB Healthy Boot
DISKPART> PS C:\training>
A fenti példában tehát egy Select és egy Detail utasítást is átadtam a Diskpart-nak. Természetesen a kimenet távolról sem objektum, hanem egy nagy sztringtömb, ami nem igazán nevezhető strukturáltnak, így lesz még ezzel dolgunk bőven.
Ahhoz, hogy partíciókat tudjunk létrehozni, érdemes egy olyan függvény létrehozásával kezdeni, amelyik információkat gyűjt össze arról, hogy egyáltalán tudunk-e még létrehozni partíciót és melyik lemezen? Ehhez a Diskpart List és a Detail műveletét is meg kell hívni. Ehhez az alábbi, Get-Disk függvényt hoztam létre. Ennek lényegi eleme a paraméterdefiníció utáni sor, amely egy nagy –match kifejezéssel megszűrt diskpart kifejezés, ami szétcincálja a list disk kimeneteként kapott sztringet. A függvény további részében ezt alakítom szebb objektummá, megküzdve a változó mértékegységekben jelzett méretek problémájával és hozzárakva a detail disk kimenetéből kinyerhető azon információt, hogy van-e már az adott lemezen partíció vagy kötet:
function Get-Disk
{
param (
[parameter(ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, Position=0)]
[int]
$id,
[switch] $free
)
"list disk" | diskpart | ?{$_ -match "\sDisk\s(?<ID>\d+)\s+(?<state>\w+)\s+(?<size>\d+)\s(?<sizemag>\w+)\s+(?<free>\d+)\s(?<freemag>\w+)\s+(?<Dyn>\*?)\s+(?<GPT>\*?)"} |
%{New-Object -TypeName PSObject -Property $matches|
Select-Object -Property *, @{
n="Size";
e={&([scriptblock]::Create("$($_.size)$(if($_.sizemag
-ne "b"){$_.sizemag})"))}
},
@{
n="Free";
e={&([scriptblock]::Create("$($_.free)$(if($_.freemag
-ne "b"){$_.freemag})"))}
},
@{
n="ID";
e={[int]$_.ID}
},
@{
n="Dyn";
e={$_.dyn -eq "*"}
},
@{
n="GPT";
e={$_.gpt -eq "*"}
} -ExcludeProperty 0, size*, free*, ID, Dyn, GPT
} |
?{if($PSBoundParameters.keys -contains "id"){$_.id -eq $id}else{$true}} |
?{if(!$free){$true}else{$_.free -gt 0}} |
%{
$volexists = ("Select
disk $($_.id)", "detail disk" | diskpart)[-3] -ne "There
are no volumes."
Add-Member -InputObject $_ -MemberType Noteproperty -Name VolumeExists -Value $volexists -PassThru
}
}
Nézzük ennek használatára példákat, illetve a kimenetét:
PS C:\training> Get-Disk | ft
state Size Free ID Dyn GPT VolumeExis
ts
----- ---- ---- -- --- --- ----------
Online 66571993088 0 0 False False True
Online 21474836480 20401094656 1 True False False
Online 10737418240 9663676416 2 True True False
PS C:\training> Get-Disk -free | ft
state Size Free ID Dyn GPT VolumeExis
ts
----- ---- ---- -- --- --- ----------
Online 21474836480 20401094656 1 True False False
Online 10737418240 9663676416 2 True True False
PS C:\training> Get-Disk -id 1 | ft
state Size Free ID Dyn GPT VolumeExis
ts
----- ---- ---- -- --- --- ----------
Online 21474836480 20401094656 1 True False False
Látható, hogy alapvetően háromfajta paraméterezéssel használhatjuk. Az első az, amikor nem adunk semmi paramétert, ilyenkor az összes diszkről kapunk információt. Ha a –free kapcsolót használjuk, akkor csak azokat a lemezeket sorolja fel, amelyeken van még szabad hely partíció létrehozására. Ha az –id paramétert adjuk meg, akkor csak az adott lemez információit kapjuk meg.
Ezután nézzük, hogyan lehet partíciót létrehozni? Elsőként érdemes összeszedni minden fontos információt a lemezről, amelyen a partíciót létre akarjuk hozni. Erre pont az előző függvényünket tudjuk felhasználni. Ezután érdemes minden hibalehetőséget megvizsgálni, még mielőtt bármit is teszünk. Ilyen hiba lehet például az, ha olyan lemezen akarunk partíciót létrehozni, ami nincs is, vagy olyanon, ahol nincs szabad hely, vagy olyan betűjelet akarunk adni, ami már foglalt, stb.
Az egyszerűség kedvéért én csak dinamikus diszkekkel foglalkozom, így ha a lemez nem dinamikus, akkor azzá alakítom. Ha a lemez nincs on-line állapotban, akkor meg azzá kell tenni. Ha a partíció kész, és fel is van csatolva, akkor én még meg is formázom.
Mindezeket az alábbi függvénnyel valósítottam meg:
function New-Diskpart
{
param (
[parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromPipeline=$true, Position=0)]
[int]
$id,
[int]
$sizeMB,
[string]
$mount,
[switch]
$gpt
)
$disk = Get-Disk
-id $id
if(!$disk){
Write-Error
"No disk with ID
$($disk.id)." -ErrorAction
stop
}
if($disk.free
-lt $sizemb*1mb){
Write-Error
"Not enough free space to create
volume on disk $($disk.id)." -ErrorAction
stop
}
if($mount -notmatch "^\w:?$"){
if(test-path
$mount){
if(@(Get-ChildItem
$mount -force).count -gt 0){
Write-Error
"The target mount point is not
empty." -ErrorAction stop
}
}
else{
$created = New-Item
-Path (split-path $mount) -Name (split-path $mount -leaf)
-ItemType directory -ErrorAction silentlycontinue
if(!$created){
Write-Error
"Could not create taget
directory for mount point $mount."
-ErrorAction stop
}
}
}
else{
if($mount -notmatch ":$"){$mount += ":"}
Get-ChildItem
$mount -ErrorAction silentlycontinue > $null
if($?){
Write-Error
"Drive letter $mount already
used." -ErrorAction stop
}
}
$tasks = @("Select disk $($disk.id)")
if($disk.state
-ne "Online"){
$tasks += "online disk"
}
if(!$disk.dyn){
$tasks += "convert dynamic"
}
if($gpt -or $sizeMB -ge 2mb){
$tasks += "CONVERT GPT"
}
if($sizeMB -gt 0){
$tasks += "CREATE VOLUME SIMPLE SIZE=$sizemb"
}
else{
$tasks += "CREATE VOLUME SIMPLE"
}
if($mount -match "^(?<letter>\w):?$"){
$tasks += "assign letter=$($matches.letter)"
}
else{
$tasks += "assign mount=$mount"
}
$tasks += "Format fs=ntfs quick"
$tasks |
diskpart
}
A New-Diskpart függvényemnek a következő paramétereket lehet átadni:
id: a lemez azonosítója, ahova a partíciót létre akarjuk hozni
sizeMB: a partíció mérete megabájtokban, ha kihagyjuk, akkor a teljes szabad terület felhasználásra kerül
mount: annak a meghajtónak a betűjele vagy az a könyvtár ahova becsatoljuk az új partíciót
gpt: ha ezt a kapcsolót szerepeltetjük, akkor a partíció nem MBR, hanem GPT típusú lesz. Ez a típus lesz alkalmazva automatikusan akkor is, ha a partíció mérete nagyobb, mint 2 TB.
Látható, hogy a hibalehetőségek kezelése után szépen kezdem összerakni azokat a tevékenységeket, amiket végre kell hajtani a sikeres végcél érdekében, kezdve onnan, hogy kiválasztom a megadott azonosítójú lemezt, ha szükséges, akkor on-line állapotba hozom, és így tovább, lezárva a formázással.