I am trying to find the path in Registry of a hardware device, which requires iterating over multiple Registry keys. I use break to exit the foreach loop after the first match is found, but for some reason, the break statement causes the outer if statement to exit without executing.
${device} = (Get-WmiObject -Class win32_pnpEntity -Filter 'Name like "HID Keyboard%"');
if ( ${device} -ne ${null} ) {
${driver_key} = (${device}.GetDeviceProperties().DeviceProperties |
Select-Object -Property data |
Select-Object -Skip 6 -First 1).data;
Get-ChildItem -Path "HKLM:\SYSTEM\ControlSet001\Enum" -Recurse -ErrorAction SilentlyContinue |
foreach {
if ( ${_}.GetValue("Driver") -eq "${driver_key}" ) {
${path} = ${_}.PSPath;
Write-Output "Found!";
break;
}
}
Write-Output "${path}"; # this does not run
}
If I comment out the break statement, it will work. But that mean the foreach loop continues to iterate after a match is found. What am I doing wrong?
By the way, what does the percentage sign in HID Keyboard% means? I usually use * instead.
breakstatement breaks you out of theifstatement as well as theforeachloop. To get your desired output, you can use areturnstatement inside aForEach-Objectloop instead of a foreach loop. Something like:ForEach-Object {if ( $_.GetValue("Driver") -eq "${driver_key}" ) {Write-Output "Found!" return $_.PSPath}}… | foreach { …. }is actually running| foreach-object { … }, not the similarly namedforeach( $x in $y) { … }, andbreakinside aforeach-objectterminates the nextforeachorswitchup the call stack (or the entire script if none) - learn.microsoft.com/en-us/powershell/module/… and stackoverflow.com/a/10420522/3156906. If you want tobreaka loop useforeach( $x in $y ) { … }rather thanforeach-object.