Find key in hash table (ContainsKey) not working - powershell

I'm loading a hash table with this:
$htA = dir | Where-Object {$_.Name -match "\.output\.[A-Z]-[0-9]\.csv"} | select name,length
When I try to search the Key column like thusly:
$htA.ContainsKey($h.name)
I get this super neat-o error:
Method invocation failed because [Selected.System.IO.FileInfo] does not contain a method named 'ContainsKey'.
At line:3 char:9
IF ($htA.ContainsKey($h.name) -eq $false) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (ContainsKey:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound**
So is this not a legit hashtable?

$htA is created as the type cast to it, in this case System.IO.FileInfo. Try this:
$htA = #{} # Initialises as an empty hash table
foreach ($file in (dir | Where-Object {$_.Name -match "\.output\.[A-Z]-[0-9]\.csv"} | select name,length))
{
$htA.Add($file.name, $file.length) # Populate hash table
}

Related

Is there a reason my Powershell script is now returning null-value expression errors?

As the title suggests, I have a script that I've been running daily to parse tables from a web page and export those to a csv. A few days ago though, I realized the script has been returning the following errors:
You cannot call a method on a null-valued expression. At C:\Users\Luke\DailyStats\NHLStats.ps1:16 char:1
+ $headers = $rows.item(1).children | select -ExpandProperty InnerText
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull Cannot index into a null array. At C:\Users\Luke\DailyStats\NHLStats.ps1:23 char:14
+ $headers = #($headers[0];'TEAM';$headers[1..($headers.Length-1)])
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray Cannot index into a null array. At C:\Users\Luke\DailyStats\NHLStats.ps1:23 char:33
+ $headers = #($headers[0];'TEAM';$headers[1..($headers.Length-1)])
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
I don't get why all of a sudden it randomly stopped working. Any and all help is greatly appreciated.
My script:
$url = "https://www.hockey-reference.com/leagues/NHL_2020.html"
#getting the data
$data = Invoke-WebRequest $url
#grab the third table
$table = $data.ParsedHtml.getElementsByTagName("table") | Select -skip 2 | Select -First 1
#get the rows of the Team Statistics table
$rows = $table.rows
#get table headers
$headers = $rows.item(1).children | select -ExpandProperty InnerText
#$headers = $headers | % { if ($_ -eq "GF") { "GFPG" } else { $_ }}
#count the number of rows
$NumOfRows = $rows | Measure-Object
#Manually injecting TEAM header and replace any headers you want to change
$headers = #($headers[0];'TEAM';$headers[1..($headers.Length-1)])
#enumerate the remaining rows (we need to skip the header row) and create a custom object
$allData = #{}
$out = for ($i=2;$i -lt $NumofRows.Count;$i++) {
#define an empty hashtable
$objHash=[ordered]#{}
#getting the child rows
$rowdata = $rows.item($i).children | select -ExpandProperty InnerText
for ($j=0;$j -lt $headers.count;$j++) {
#add each row of data to the hash table using the correlated table header value
$objHash[$headers[$j]] = $rowdata[$j]
}
#turn the hashtable into a custom object
[pscustomobject]$objHash
$allData.Add($i, $objHash)
}
$out | Select TEAM,AvAge,GP,W,L,OL,PTS,PTS%,GF,GA,SOW,SOL,SRS,SOS,TG/G,EVGF,EVGA,PP,PPO,PP%,PPA,PPOA,PK%,SH,SHA,PIM/G,oPIM/G,S,S%,SA,SV%,SO -SkipLast 1 | Export-Csv -Path "C:\Users\Luke\DailyStats\$((Get-Date).ToString("'NHL Stats' yyyy-MM-dd")).csv" -NoTypeInformation
Looks like your $table variable is returning null. When running that |select -skip 2 | select -first 1, it isn't returning any data to the $table variable.
This seems to be related to the -skip 2 selection.
When running just the portion of the $table = $data.ParsedHtml...
It only returns two objects.
So possibly you need to update your selection to properly retrieve the table that you want?
I am only seeing the 'standings EAS' and 'standings WES' tables being pulled.

Powershell: Updating string in hash table

I have a collection of custom objects and need to do the following steps for each object:
Replace "Team1 Group" with "Team2 Group"
Save the resulting update to a hash table, which I will pass to an API
The objects look like this:
id : 1
groupId : 1
name : Customer1 Dashboard
fullName : Customer Dashboards/Team2 Group/Customer1 Group/Customer1 Dashboard
groupName : Customer1 Group
groupFullPath : Customer Dashboards/Team2 Group/Customer1 Group
widgetTokens : { #{type = owned; name = defaultResourceGroup; value = Client Teams/Team1 Group/Customers/Customer1*; inheritList = System.Object[] }, #{type = owned; name = defaultWebsiteGroup; value = Client Teams/Team1 Group/Customers/Customer1; inheritList = System.Object[]}}
This is what I have so far:
Foreach ($dashboard in $allDashboards) {
$dashboardProperties = #{ }
$dashboard.psobject.properties | ForEach-Object { $dashboardProperties[$_.Name] = $_.Value }
#($dashboardProperties.GetEnumerator()) | Where-Object { $_.Name -eq 'widgetTokens' } | Select-Object -ExpandProperty Value | Where-Object { $_.Value -match "Team1 Group" } | ForEach-Object { $dashboardProperties[$_.Key] = #($_.value.replace('Team1 Group', 'Team2 Group')) }
$dashboardProperties
#Code to interact with an API
}
Because there are two items that match the "#($dashboardProperties.GetEnumerator()) | Where-Object { $_.Name -eq 'widgetTokens' }..." line (at least, I think that's why), I am getting the following error:
Index operation failed; the array index evaluated to null.
At line:1 char:200
+ ... ch-Object { $dashboardProperties[$_.Key] = #($_.value.replace('Team1 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
Index operation failed; the array index evaluated to null.
At line:1 char:200
+ ... ch-Object { $dashboardProperties[$_.Key] = #($_.value.replace('Team1 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
When I run this, I see both lines, as expected:
#($dashboardProperties.GetEnumerator()) | Where-Object { $_.Name -eq 'widgetTokens' } | Select-Object -ExpandProperty Value | Where-Object { $_.Value -match "Team1 Group" }
I am not sure how to move past this, any thoughts?
Thanks
Based on feedback from Reddit, looks like this should work:
$DashboardProperties.WidgetTokens |
Where-Object { $_['Name'] -eq 'widgetTokens' -and $_['Value'] -match 'Team1 Group' } |
ForEach-Object { $_['Value'] = $_['Value'] -replace '1','2' }

I can't get Powershell StartsWith function to work

I'm trying to create a Powershell script that prints out only certain AD groups from the Folder Permission settings. However for some reason Powershell doesn't recognize StartsWith function.
("C:\folder" | get-acl).Access | ForEach-Object { if (($_.IdentityReference).StartsWith("sl_test")) { continue }; $_ }
When I run this I got errors similar to this for every foreach object:
Method invocation failed because [System.Security.Principal.NTAccount] does not contain a method named 'StartsWith'.
At C:\temp\test.ps1:1 char:56
+ ("C:\folder" | get-acl).Access | ForEach-Object { if (($_.IdentityReference).St ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any suggestions on how to get this to work?
IdentityReference is a [System.Security.Principal.NTAccount]according to your error message.
But .StartWith is a method on the String type. If you call a method, Powershell does no magic for you, AFAIK.
Try ... ($_.IdentityReference) -match "^sl_test" ..., which should do the implicit string conversion.
If you want the string representation of an IdentityReference (regardless of whether it's and NTAccount object or a SID), you can reference the Value property:
$_.IdentityReference.Value.StartsWith('sl_test')
Try:
Get-Acl -Path "C:\folder" | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "sl_test*" }
You can customize the output with an additional | Select-Object -Property XY

List all azure resources with tagnames and tagvalues using PowerShell

I am trying to fetch OperatingHours tag details for all the Azure VirtualMachines and Azure SqlDatabases.
Following are the possibility for appID in a resource and the values I need to print in output correspondingly:
If OperatingHours tag itself is not present in any resource then display "Tag not present"
if OperatingHours tag is present but contains null or empty string then display "NULL/EMPTY"
if OperatingHours tag is present with any other value then display that value.
Do I need to take care of option (2) separately or is it like printing any normal value of the OperatingHours.
After long efforts I have created following script:
$ErrorOccured = $false
$resources = Get-AzureRmResource |
Where-Object {($_.ResourceType -eq "Microsoft.Compute/virtualMachines") -or ($_.ResourceType -eq "Microsoft.Sql/servers/databases")} |
foreach {
new-object psobject -Property #{
ResourceName = $_.ResourceName;
ResourceType = $_.ResourceType;
OperatingHours= try {
$ErrorActionPreference = 'SilentlyContinue';
($_ | select -expand Tags).OperatingHours; }
catch {
$ErrorOccured = $true ; }
if ($ErrorOccured)
{ "Tag not present" }
else {
($_ | select -expand Tags).OperatingHours;
$ErrorOccured = $false };}
}
$resources | Format-Table
When running this script, I am receiving following error:
At line:13 char:58
+ }
+ ~
The hash literal was incomplete.
At line:20 char:2
+ }
+ ~
Unexpected token '}' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : IncompleteHashLiteral
If I replace the OperatingHours statement with following code then the script is running with success. But in doing so, I am not able to satisfy the option (1) mentioned above.
Operating Hours = if (!($_ | select -expand Tags).OperatingHours)
{"Tag not present"}
else {($_ | select -expand Tags).OperatingHours} ;
Please advise me on how to correct this and get the required output.
Thanks
After alot of hit and trial and rigorous testing, I found what I was looking for:
OperatingHours = if ( ($_ | select -expand Tags).OperatingHours -ieq $null )
{"TAG NOT PRESENT"}
elseif ( ($_ | select -expand Tags).OperatingHours -ieq '')
{"NULL/EMPTY"}
else
{($_ | select -expand Tags).OperatingHours } ;
I replaced the OperatingHours statement in original script to above.
The solution looks easy and after finding it I was like how could I miss that earlier, but that's what learning process is all about, right ?

When piping array of integers the $_ variable is null?

Take this as an example:
$var = "one","two","three"
0..2 | select-object $var[$_]
Index operation failed; the array index evaluated to null.
At line:1 char:27
+ 0..2 | select-object $var[ <<<< $_]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
Why is $_ a null?
I can't figure why you are using select-object
try this:
$var = "one","two","three"
0..2 | % { $var[$_]}
You can also use select-object in a different way:
$var | select -Index (0..2)
And btw, if all you want to do is extract element in the array, you can do array slicing:
$var[0..2]
If you want to use select-object you need to create a hashtable, aka calculated property, and give it a name and expression keys. The result would be objects with one property, var, in the following example
0..2 | select #{name='var';expression={$var[$_]}}
var
---
one
two
three