Where-Object filters objects after they enter a PowerShell pipeline, retaining only those that satisfy a condition. It is useful for simple operational checks, such as selecting a virtual hard disk by path or raw disks by partition style. section 10.8.1
Filtering late has a cost: PowerShell examines each returned record one at a time. When a data source or cmdlet provides its own filter, constrain the results there first. Database-side filtering avoids transferring unneeded rows and can use SQL query optimization; Get-ChildItem -Filter avoids returning every file before PowerShell narrows the list. section 7.4 section 3.3.1
Use Where-Object when the needed test applies to pipeline objects and no earlier filter is the better fit:
- Select the VHD already associated with a VM by comparing each hard drive's Path property with the expected data-disk path. section 10.8.1
- Return only disks whose PartitionStyle is raw, then pipe them through initialization, partition creation, and formatting. section 10.8.1
- Avoid it for SQL result selection or filename-only filtering when a SQL WHERE clause or Get-ChildItem -Filter can restrict results before PowerShell receives them. section 7.4 section 3.3.1
Configure only uninitialized disks
A disk-provisioning pipeline can begin with Get-Disk, filter for PartitionStyle equal to raw, and pass only those disks to Initialize-Disk, New-Partition, and Format-Volume. Because the filter excludes initialized disks, repeating the operation does not require extra checks for disks already configured. section 10.8.1
Listing 10.11 Adding a second VHD
Function Add-SecondVHD{
param(
$VM
)
$Path = @{ #1
Path = $VM.Path
ChildPath = "$($VM.Name)-Data.vhdx"
}
$DataDisk = Join-Path @Path
if (-not(Test-Path $DataDisk)) { #2
New-VHD -Path $DataDisk -SizeBytes 10GB | Out-Null
}
$Vhd = $VM.HardDrives | #3
Where-Object { $_.Path -eq $DataDisk }
if (-not $Vhd) {
$VM | Get-VMScsiController -ControllerNumber 0 |
Add-VMHardDiskDrive -Path $DataDisk
}
}
Add-SecondVHD -VM $VM
$ScriptBlock = { #4
$Volume = @{
FileSystem = 'NTFS'
NewFileSystemLabel = "Data"
Confirm = $false
}
Get-Disk | Where-Object { $_.PartitionStyle -eq 'raw' } |
Initialize-Disk -PartitionStyle MBR -PassThru |
New-Partition -AssignDriveLetter -UseMaximumSize |
Format-Volume @Volume
}
$Command = @{ #5
VMId = $VM.Id
ScriptBlock = $ScriptBlock
Credential = $Credential
ErrorAction = 'Stop'
}
$Results = Invoke-Command @Command
$Results
Inspect the complete VHD automation listing to see Where-Object select an existing drive by Path and filter raw guest disks before configuration. section 10.8.1

