Powershell Item-Property not expanded when stored to an array with Get-ChildItem

359 views Asked by At

Writing a Posh 2.0 compliant script (a requirement), I need to get details of services using the registry base.

However when I search for a specific service using the exact name (and thus using -eq or -like), the results are incorrect while with -like using wildcards, this works as intended. How could we explain this?

PS > [array]$services=Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "*OpenVpnService*" }
PS > $services[0]


    Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services


SKC  VC Name                           Property
---  -- ----                           --------
  0   8 OpenVpnService                 {Type, Start, ErrorControl, ImagePath...}

PS > "'$($services[0].PsChildName)'"
'OpenVpnService'

PS > [array]$services=Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -eq "OpenVpnService" }
PS > $services[0]

SKC  VC Name                           Property
---  -- ----                           --------
  0   8

PS > "'$($services[0].PsChildName)'"
''

PS > [array]$services=Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "OpenVpnService" }
PS > $services[0]

    SKC  VC Name                           Property
    ---  -- ----                           --------
      0   8

PS > "'$($services[0].PsChildName)'"
''

UPDATE: Since I need a complete Posh 2.0 compliant machine, I have a brand new VM with Windows 7 SP1 Ultimate installed without any updates. Why without any updates? Because by updating the machine, I would get a more recent .NET version and Posh patches. I tested on a Windows 10 machine fully up to date and this is working flawlessly, the Windows 7 test machine also succeed as long as you do not store the output to an array.

2

There are 2 answers

0
wget On BEST ANSWER

After a few hours trying to debug the situation and narrowing the issue, I have been able to determine what was causing the issue.

The array initialization/casting was failing. Simply surrounding the content that needed to be casted by the array subexpression operator @( ) solved the issue.

It seems like the way arrays are handled has changed on more recent PowerShell versions (5.1 on Windows 10, and PowerShell 2.0 on a not updated Windows 7), especially with PowerShell 3.0 which introduced changes in collections and dictionaries

PS > [array]$services=@(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "*OpenVpnService*" })
PS > $services[0]


    Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services


SKC  VC Name                           Property
---  -- ----                           --------
  0   8 OpenVpnService                 {Type, Start, ErrorControl, ImagePath...}

PS > "'$($services[0].PsChildName)'"
'OpenVpnService'

PS > [array]$services=@(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -eq "OpenVpnService" })
PS > $services[0]


    Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services


SKC  VC Name                           Property
---  -- ----                           --------
  0   8 OpenVpnService                 {Type, Start, ErrorControl, ImagePath...}

PS > "'$($services[0].PsChildName)'"
'OpenVpnService'

PS > [array]$services=@(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "OpenVpnService" })
PS > $services[0]


    Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services


SKC  VC Name                           Property
---  -- ----                           --------
  0   8 OpenVpnService                 {Type, Start, ErrorControl, ImagePath...}

PS > "'$($services[0].PsChildName)'"
'OpenVpnService'
4
sodawillow On

If you know the service name already, you can do this:

$serviceName = "WinRM"

# registry
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
[bool](Get-ItemProperty -Path $regPath -Name DelayedAutoStart -ErrorAction 0)

# WMI
(Get-WmiObject Win32_Service |
    Where-Object { $_.Name -eq $serviceName }).DelayedAutoStart

# result = True

$serviceName = "spooler"

# registry
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
[bool](Get-ItemProperty -Path $regPath -Name DelayedAutoStart -ErrorAction 0)

# WMI
(Get-WmiObject Win32_Service |
    Where-Object { $_.Name -eq $serviceName }).DelayedAutoStart

# result = False