I am fairly new to PowerShell and I want for a USB key plugged, to retrieve some info. Right now my script is:
Get-WmiObject win32_diskdrive |
ForEach-Object{
$disk = $_
$_.GetRelated('Win32_PnPEntity')|
ForEach-Object{
$pnp = $_
$_.GetRelated('Win32_USBController') |
ForEach-Object{
$usb = $_
[pscustomobject]@{
SerialNumber = $disk.SerialNumber
Model = $disk.Model
Size = $disk.Size
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {VID=$matches['vid']; PID=$matches['pid']}
}
}
}
}
The line beginning with
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {VID=$matches['vid']; PID=$matches['pid']}
does not work. I want to translate deviceid (which I can get by doing USBDeviceID = $usb.DeviceID
) ID in PID UID directly.
It throws the following error
Error with code “Missing = operator after key in hash literal" for the statement "if ($usb.DeviceID -match '.* ...
What am I missing ? many thanks for helping me .
Gerald
This is because the way you intend to add properties to the PsCustomObject is wrong.
Either do this:
$result = [PsCustomObject]@{
SerialNumber = $disk.SerialNumber
Model = $disk.Model
Size = $disk.Size
}
# add items to the object if the condition is true
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {
$result | Add-Member -MemberType NoteProperty -Name 'VID' -Value $matches['vid']
$result | Add-Member -MemberType NoteProperty -Name 'PID' -Value $matches['pid']
}
# output the PsCustomObject
$result
or use a Hashtable as temporary storage:
# create a Hastable to temporarily store results in
$hash = [ordered]@{
SerialNumber = $disk.SerialNumber
Model = $disk.Model
Size = $disk.Size
}
# add items to the hash if the condition is true
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {
$hash['VID']=$matches['vid']
$hash['PID']=$matches['pid']
}
# next cast to PsCustomObject and output
[PsCustomObject]$hash
Nowadays you should not use Get-WMIObject
anymore and instead use Get-CimInstance
.
The code could then be rewritten as below:
$result = Get-CimInstance -ClassName Win32_DiskDrive |
Where-Object {$_.InterfaceType -eq 'USB'} |
ForEach-Object {
$out = [PsCustomObject]@{
SerialNumber = $_.SerialNumber
Model = $_.Model
Size = $_.Size
VID = 'N/A'
PID = 'N/A'
}
# if the condition is true update the .VID and .PID values
if ($_.PNPDeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {
$out.VID = $matches['vid']
$out.PID = $matches['pid']
}
# output the object to be collected in variable $result
$out
}
$result | Format-Table -AutoSize
a demo output would look like this:
SerialNumber Model Size VID PID
------------ ----- ---- --- ---
000000264001 Generic Ultra HS-SD/MMC USB Device N/A N/A
0018F3D97163BB918148003C Kingston DT R400 USB Device 15989944320 N/A N/A
Regex details
. Match any single character that is not a line break character
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
VID_ Match the characters “VID_” literally
(?<vid> Match the regular expression below and capture its match into backreference with name “vid”
[0-9A-F] Match a single character present in the list below
A character in the range between “0” and “9”
A character in the range between “A” and “F” (Case-Insensitive)
{4} Exactly 4 times
)
&PID_ Match the characters “&PID_” literally
(?<pid> Match the regular expression below and capture its match into backreference with name “pid”
[0-9A-F] Match a single character present in the list below
A character in the range between “0” and “9”
A character in the range between “A” and “F” (Case-Insensitive)
{4} Exactly 4 times
)
. Match any single character that is not a line break character
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)