Sunil
Sunil

Reputation: 95

Foreach and array variables in powershell

I am importing a CSV and recycling that site based on the values in the CSV. The csv is dynamically buildup based on the alerts we receive. When I try the following code I receive an values printed and errors

import-csv d:\emscripts\recy\recycle.txt -Header "site","IP","Log" | foreach {
    $_.IP
    $_.site
    $appPool = Get-WmiObject -Authentication PacketPrivacy -Impersonation Impersonate  -ComputerName $_.IP -namespace "root/MicrosoftIISv2"  -class IIsApplicationPool | Where-Object {$_.Name -eq "W3SVC/AppPools/$($_.site)" }
    $appPool.Recycle()
    }

*192.168.100.182 Testsite1 You cannot call a method on a null-valued expression. At line:5 char:5 + $appPool.Recycle() + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull

192.168.100.131 testsite2 You cannot call a method on a null-valued expression. At line:5 char:5 + $appPool.Recycle() + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull*

You can see that the values are printed but it is failing to get anything into the $appPool.

I have changed it to the following and it is working as expected.

    $RecyleSites  = import-csv recycle.txt -Header "site","IP","Log" 
foreach ($site in $RecyleSites)  {
    $site.IP
    $site.site
    $appPool = Get-WmiObject -Authentication PacketPrivacy -Impersonation Impersonate  -ComputerName $site.IP -namespace "root/MicrosoftIISv2"  -class IIsApplicationPool | Where-Object {$_.Name -eq "W3SVC/AppPools/$($site.site)" }
    $appPool.Recycle()
    }

I am trying understand what I am doing wrong in the first set of code ?

Upvotes: 0

Views: 1290

Answers (2)

campbell.rw
campbell.rw

Reputation: 1386

I think that this piece of code from your original sample contains your problem:

Where-Object {$_.Name -eq "W3SVC/AppPools/$($_.site)

$_.site isn't in scope any more because $_ now represents the current object in the Where-Object "loop". When you printed $_.site as the first line of the foreach loop, $_ still represented the current item in the $RecycleSite list.

Upvotes: 2

Matt
Matt

Reputation: 46730

There is a scope issue here for sure. You need to save the variable $_.Site for later use.

$site = $_.site
$appPool = Get-WmiObject -Authentication PacketPrivacy -Impersonation Impersonate  -ComputerName $_.IP -namespace "root/MicrosoftIISv2"  -class IIsApplicationPool | 
    Where-Object {$_.Name -eq "W3SVC/AppPools/$site" }
$appPool.Recycle()

$_ always refers to the object in scope. Saving variables outside of that scope for use is a common practice.

Your ForEach construct is doing just that by saving the assigning the variable in each pass to $site

Upvotes: 1

Related Questions