Thursday, April 19, 2012

Powershell overlapping pipeline problem

During the recent Microsoft 2012 scripting games, I encountered an interesting problem which really threw me off for a few hours. When trying to link up WMI results with registry entries in the Advanced 8 event, I ended up with a lot of Get-ItemProperty failures, where the values being read in my registry access where actually results from my WMI lookups. Here is a sample of the code

function get-physicalphysical {
     param(  [parameter(position=0)][string]$nicGUID   )
    $vals = Get-ChildItem hklm:"\System\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}" |
          get-itemproperty -name $ | where {$_.netcfginstanceid -match $nicGuid}
    if ($vals.characteristics -eq 0x84) { return $true } else { return $false }

$nics = Get-WmiObject -Class Win32_NetworkAdapter -Filter "PhysicalAdapter = True" |
where {get-physicalphysical $($_.guid)}

So we have GWMI for network adapters piped to a function called get-physicalphysical.  The guid of the WMI network adapter result is searched in the registry for lower level details that are not available via WMI.  The error we get is something like this (repeating many times and for different adapter names)

Get-ItemProperty : Property Intel(R) 82567LM Gigabit Network Connection does not exist at path HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0000.
At line:11 char:25
+         get-itemproperty <<<<  -name $ | where {$_.netcfginstanceid -ma
tch $nicGuid}
    + CategoryInfo          : InvalidArgument: (Intel(R) Connect
   ion:String) [Get-ItemProperty], PSArgumentException
    + FullyQualifiedErrorId : System.Management.Automation.PSArgumentException

In this case, the WMI results have a property called Name, and the entries in the registry that we were looking at also have a value for Name.  What we want is the name of the registry key that contains the configurations for the adapter.  But with the use of two pipelines, it appears that the $_ referenced in the pipeline within the function is accessing the pipeline $_ from outside of the function.  I'm not expert in low level powershell details and how the pipeline works, but after playing around a bit with trying to scope the $_ variable, and eventually reading the about_functions help, I found that you can scope a function.  By scoping the function and the $_ variable within it (using the same scope), I was able to separate the two pipelines and accomplish what I was hoping for.  You can see the full code at the entry script.

No comments:

Post a Comment