0

I'm attempting to search a hash table that contains a hostname as the key and applications as the values. I'm looking for hostnames (keys) that do NOT contain a specific value AKA application. However, my code does not appear to work as I always receive all of the keys/hostnames back.

foreach ($global:computer in $global:hash.keys){  
  if ($global:hash.$global:computer.values -notcontains 'SnagIt'){
    $global:computer
}

}

Example Data:

Key, Values

Host1:FireFox,Chrome,IE

Host2:Snagit,FireFox,Chrome,IE

Host3:Chrome,IE

Example Value Output from $global:hash.$global:computer:

{Snagit, FireFox, Chrome, IE...}

Hash Table Build Code:

$global:Csv = Import-Csv -LiteralPath $global:ConvertedSNWReport

[HashTable]$global:Hash=@{}

For ($i = 0; $i -lt ($global:Csv."Computer name").Count; $i++)
{
If ($global:Hash.ContainsKey($global:Csv[$i].'Computer name'))
{
    $global:Hash.($global:Csv[$i].'Computer name').Application += $global:Csv[$i].Application
    Continue
}
$global:Hash.($global:Csv[$i].'Computer name') = @{
  Application = @($global:Csv[$i].Application)
}
}
8
  • Remove .values Commented Aug 30, 2017 at 17:18
  • That didn't appear to work for me. Commented Aug 30, 2017 at 17:19
  • 1
    I don't think your hashtable looks like you think it does. The index operator ([]) belongs after the list variable, not after the property, e.g. $global:Csv[$i].'Computer name'. Commented Aug 30, 2017 at 17:38
  • I changed it and it didn't seem to make a difference, as far as I could tell. Commented Aug 30, 2017 at 17:45
  • 1
    Ah, I see. You need to use $Hash.Computer.Application to get the array of programs for that PC. Commented Aug 30, 2017 at 18:26

2 Answers 2

1

Your hashtable creation builds the application lists as nested hashtables:

{
    "Host1": {
        "Application": [ "FireFox", "Chrome", "IE" ]
    },
    "Host2": {
        "Application": [ "Snagit", "FireFox", "Chrome", "IE" ]
    },
    "Host3": {
        "Application": [ "Chrome", "IE" ]
    }
}

Import your data like this:

$hash = @{}
Import-Csv -LiteralPath $global:ConvertedSNWReport | ForEach-Object {
    $hash[$_.'Computer name'] += @($_.Application)
}

to get a direct mapping between hostname and list of applications:

{
    "Host1": [ "FireFox", "Chrome", "IE" ],
    "Host2": [ "Snagit", "FireFox", "Chrome", "IE" ],
    "Host3": [ "Chrome", "IE" ]
}

With that you can filter the hashtable like this:

$hash.GetEnumerator() | Where-Object {
    $_.Value -notcontains 'Snagit'
}

If you want to stick with your data import procedure (which I do not recommend) you need to expand the Application key of the hashtable values:

$hash.GetEnumerator() | Where-Object {
    $_.Value.Application -notcontains 'Snagit'
}

As a side note: avoid using global variables whenever you can. They're usually a side channel that introduces unexpected state in your scripts. Particularly do not use global variables as loop variables. In most cases it's better to use local variables and pass data from a caller via script/function parameters.

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

4 Comments

"Doesn't work" is an insufficient problem description. Please update your question with how your hashtable is actually defined, like Mathias already requested.
Sorry for the confusion, please see the updated post.
Thank you very much for this.
Bonus points if you can show how you can do a -notlike or -notmatch 'Snagit'
0

The expression $hashtable.$key already resolves to the values of the entry with key $key

Remove the .values reference from $global:hash.$global:computer.values

If the values are just single strings with comma-separated items, -notcontains won't work, use the -notlike operator instead:

if($hash.$computer -notlike '*SnagIt*'){...}

4 Comments

@MrMr Updated the answer. Can you perhaps update your answer with how you constructed the hashtable in the first place?
the second option you provided didn't work either. I used import-csv to build the hash table.
@MrMr Import-Csv produces a list of objects, not a hashtable. Please update your question with a sample of your actual input data and how you read them. Basically, put a minimal reproducible example in your question.
I apologize, I used import-csv and then I built a hash table with that data.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.