1

I'm having trouble terminating a foreach-object loop in PowerShell v2. For a rough idea of the task I'm trying to accomplish, here's the pseudo-code:

  • Read lists of host machines from a text file
  • For each host in the text file get Win32_Product (filtered against an exclusion list), convert output to html and save.

The reason for the script is that I've amassed a text file listing all applications included on standard client images, and would like to periodically scan hosts from another text file to see if there are any unauthorized, sketchy or otherwise unnecessary applications on the host machines.

The code does work in a rough sense, but the main issue I'm having is that the script will not terminate without manual intervention. I guess the component I'm missing here is to run the loop until some condition exists (ie. first line in the host file is encountered for the second time), then terminates the script. Although this is the method I've envisioned, I am always open to other logic, especially if its more efficient.

Here's the actual code:

Get-Content c:\path\to\testhostlist.txt | Foreach-Object {
Get-WmiObject Win32_Product | 
Where-Object { $_.Name -f "'C:\path\to\testauthapplist.txt'" | 

ConvertTo-Html name,vendor,version -title $name -body "<H2>Unauthorized Applications.</H2>"}} |

Set-Content c:\path\to\unauthapplisttest.html  
3
  • I don't understand your code. The Where-Object filter isn't testing a condition. $_.Name -f "'C:\path\to\testauthapplist.txt'" doesn't make sense, because $_.Name isn't a format string. Perhaps there was a copy/paste error? It seems like there's something missing between $_.Name and -f. Also, how would the first line of the host file be encountered a second time if you're only listing it once? This doesn't even seem to be an infinite loop that would need an exit condition. Foreach-Object doesn't repeat indefinitely. Maybe it's just getting stuck because the code is mangled. Commented Jan 15, 2014 at 0:39
  • Please explain what you're trying to accomplish with Where-Object { $_.Name -f "'C:\path\to\testauthapplist.txt'" |. I suspect that the problem is that that's not the correct syntax for whatever you're trying to do. Commented Jan 15, 2014 at 0:41
  • I suspect it will terminate. It's just extremely slow. Get-WmiObject Win32_Product is very slow, and you are doing it for each line in your input file. You should do it once at the beginning and keep the result in a list. I agree with Adi that your where-object is strange. I think you need to take a step back and rework the whole thing. Commented Jan 15, 2014 at 0:42

3 Answers 3

2

I don't see how the first line of the host file (I infer you mean testhostlist.tx) would ever be encountered a second time, since you're only listing it once. This doesn't even seem to be an infinite loop that would need an exit condition. Foreach-Object doesn't repeat indefinitely.

It seems to me that the problem is not that the loop doesn't exit without a condition, it's that the syntax is invalid.

  1. Where-Object filters the pipeline by passing only objects that meet a certain condition, but the scriptblock that follows doesn't perform a boolean test.
  2. In fact, the content of the scriptblock doesn't appear valid in and of itself. -f is the format operator, and takes a format string as the left operand, but $_.Name is not a format string.

I'm going to take a guess here, based on your description, that the idea is to filter the results of Get-WmiObject Win32_Product for objects whose Name property isn't listed in testauthapplist.txt (I take it that's the "exclusion list" you're referring to). If so, this is the correct syntax:

Get-Content c:\path\to\testhostlist.txt | %{
  Get-WmiObject Win32_Product | ?{
    (Get-Content 'C:\path\to\testauthapplist.txt') -notcontains $_.Name
  } | ConvertTo-Html name,vendor,version -title $name -body "<H2>Unauthorized Applications.</H2>"
} | Set-Content c:\path\to\unauthapplisttest.html

(Note that %{} and ?{} are just abbreviations for Foreach-Object and Where-Object, respectively.)

Sign up to request clarification or add additional context in comments.

Comments

1

If i understood you correctly you are trying to stop your Script completely? If so did you try Break? If you only want to skip a loop use continue

Comments

0
$hostlist = Get-Content c:\path\to\testhostlist.txt 
$a = @()
Foreach($item in $hostlist)
{
    $a += "<style>"
    $a += "BODY{background-color:gray;}"
    $a += "TABLE{margin: auto;border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
    $a += "TH{border-width: 1px;padding: 4px;border-style: solid;border-color: black;background-color:yellow}"
    $a += "TD{border-width: 1px;padding: 4px;border-style: solid;border-color: black;background-color:white}"
    $a += "h2{color:#fff;}"
    $a += "</style>"

    Get-WmiObject Win32_Product | select name,vendor,version | sort name | ConvertTo-Html -head $a -body "<Center><H2>Unauthorized Applications.</H2></Center>" | Out-File c:\path\to\$item"-applist.html"
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.