Parsing and modifying a powershell object - powershell

I'm parsing HTML from a webserver (specifically a Fanuc controller) and assigning the innerText to a object.
#Make sure the controller respons
if ($webBody.StatusCode -eq 200) {
Write-Host "Response is Good!" -ForegroundColor DarkGreen
$preBody = $webBody.ParsedHtml.body.getElementsByTagName('PRE') | Select -ExpandProperty innerText
$preBody
}
The output looks a little like so:
[1-184 above]
[185] = 0 ''
[186] = 0 ''
[187] = 0 ''
[188] = 0 ''
[189] = 0 ''
[and so on]
I only want to read the data from 190, 191, 193 for example.
What's the best way to do this? I'm struggling to sanitize the unwanted data in the object.
Currently I have a vbscript app that outputs to a txt file, cleans the data then reads it back and manipulates it in to a sql insert. I'm trying to improve on it with powershell and keen to try and keep everything within the program if possible.
Any help greatly appreciated.

With the assumption that the data set is not too large to place everything into memory. You could parse with regex into a PowerShell Object, then you can use Where-Object to filter.
#Regex with a capture group for each important value
$RegEx = "\[(.*)\]\s=\s(\d+)\s+'(.*)'"
$IndexesToMatch = #(190, 191, 193)
$ParsedValues = $prebody.trim | ForEach-Object {
[PSCustomObject]#{
index = $_ -replace $regex,'$1'
int = $_ -replace $regex,'$2'
string = $_ -replace $regex,'$3'
}
}
$ParsedValues | Where-Object { $_.index -in $IndexesToMatch }
Input :
[190] = 1 'a'
[191] = 2 'b'
[192] = 3 'c'
[193] = 4 'd'
[194] = 5 'e'
Output :
index int string
----- --- ------
190 1 a
191 2 b
193 4 d

Related

Adding a column to a datatable in powershell

I am trying to add a column to data I have imported (and will export) as a CSV.
I am importing a CSV:
What I want to do add another column, perhaps "10/15/22" when the process runs, and then update the values under that date.
In effect, the document will grow to the right, adding a column each time it is run.
I have an object called $test. It will have values like:
$test.users = "7"
$test.SomeBSValue = "22"
$test.Computers = "52"
When all is said and done, my output should look like:
Adding to the list any values I have that are not part of the list already, but recording the values I have under the heading for the date.
So, if the script is run and collects 100 data points, those data point would all be in the CSV under the date.
I would have thought this would be easy, but now I am drawing a complete blank.
I've considered (but have not coded) even trying to put into a GUI grid view and then reading the data back and writing the CSV (but there should be an easier way, right?)
Since you don't actually use it as a CSV we can treat it like regular content.
Say we have a file in C:\test called test.csv that looks as follows:
"Settings","08/15/22","09/15/22"
"Users",0,0
"Computers",0,1
"SomeValue1",0,2
"SomeValue2",0,2
"SomeValue3",0,2
"Stat1",0,10
"Stat2",7,0
"Stat3",0,0
"SomeBSValue",1,2
We can import it, add the row from the object to each corresponding row and right the file to test2.csv.
$test = #{
Settings = "10/15/22"
users = "7"
Computers = "52"
SomeValue1 = "22"
SomeValue2 = "24"
SomeValue3 = "25"
Stat1 = "4"
Stat2 = "3"
Stat3 = "2"
SomeBSValue = "1"
}
$content = Get-Content "C:\test\test.csv"
$newContent = #()
foreach($row in $content){
foreach($key in $test.Keys){
if($row -like "*$key*"){
$row = $row + "," + $test."$key"
$newContent += $row
}
}
}
$newContent | Out-File "C:\test\test2.csv"
After running the script it will have added the values from the object:
"Settings","08/15/22","09/15/22",10/15/22
"Users",0,0,7
"Computers",0,1,52
"SomeValue1",0,2,22
"SomeValue2",0,2,22
"SomeValue3",0,2,22
"Stat1",0,10,4
"Stat2",7,0,4
"Stat3",0,0,4
Edit:
If you want the date between quotes, replace $row = $row + "," + $test."$key" with this:
if($key -eq "Settings"){
$row = $row + "," + '"' + $test."$key" + '"'
}else{
$row = $row + "," + $test."$key"
}
This idea is pretty terrible idea, as you stated, "grow to the right" is definitely not a good approach and you should consider a better way of doing it, data should always expand vertically.
As for the solution, you can create new columns easily with Select-Object and dynamically generated calculated properties.
Note, this should definitely not be considered an efficient approach. This will be slow because Select-Object is slow.
function Add-Column {
param(
[Parameter(ValueFromPipeline, DontShow, Mandatory)]
[object] $InputObject,
[Parameter(Mandatory)]
[string] $ColumnName,
[Parameter(Mandatory)]
[string] $ReferenceProperty,
[Parameter(Mandatory)]
[hashtable] $Values
)
begin {
$calculatedProp = #{ N = $ColumnName }
}
process {
$calculatedProp['E'] = { 0 }
if($value = $InputObject.$ReferenceProperty) {
if($Values.ContainsKey($value)) {
$calculatedProp['E'] = { $Values[$value] }
}
}
$InputObject | Select-Object *, $calculatedProp
}
}
Usage
Import-Csv path\to\csv | Add-Column -ColumnName '09/15/22' -ReferenceProperty Settings -Values #{
users = "7"
SomeBSValue = "22"
Computers = "52"
}
Result
Settings 08/15/22 09/15/22
-------- -------- --------
Users 0 7
Computers 0 52
SomeValue1 0 0
SomeValue2 0 0
SomeValue3 0 0
Stat1 0 0
Stat2 7 0
Stat3 0 0
SomeBSValue 1 22
This function allows then pipe into Export-Csv at ease:
Import-Csv path\to\csv | Add-Column ... | Export-Csv path\to\newCsv

How can subtract a character from csv using PowerShell

I'm trying to insert my CSV into my SQL Server database but just wondering how can I subtract the last three character from CSV GID column and then assigned it to my $CSVHold1 variable.
My CSV file look like this
GID Source Type Message Time
KLEMOE http://google.com Od Hello 12/22/2022
EEINGJ http://facebook.com Od hey 12/22/2022
Basically I'm trying to get only the first three character from GID and pass that value to my $CSVHold1 variable.
$CSVImport = Import-CSV $Global:ErrorReport
ForEach ($CSVLine1 in $CSVImport) {
$CSVHold1 = $CSVLine1.GID | ForEach-Object { $_.$GID = $_.$GID.subString(0, $_.$GID.Length - 3); $_ }
$CSVGID1 = $CSVLine1.GID
$CSVSource1 = $CSVLine1.Source
$CSVTYPE1 = $CSVLine1.TYPE
$CSVMessage1 = $CSVLine1.Message
}
I'm trying to do like above but some reason I'm getting an error.
You cannot call a method on a null-valued expression.
Your original line 3 was/is not valid syntax as Santiago pointed out.
$CSVHold1 = $CSVLine1.GID | ForEach-Object { $_.$GID = $_.$GID.subString(0, $_.$GID.Length - 3); $_ }
You are calling $_.$GID but you're wanting $_.GID
You also don't need to pipe the object into a loop to achieve what it seems you are asking.
#!/usr/bin/env powershell
$csvimport = Import-Csv -Path $env:HOMEDRIVE\Powershell\TestCSVs\test1.csv
##$CSVImport = Import-CSV $Global:ErrorReport
ForEach ($CSVLine1 in $CSVImport) {
$CSVHold1 = $CSVLine1.GID.SubString(0, $CSVLine1.GID.Length - 3)
$CSVGID1 = $CSVLine1.GID
$CSVSource1 = $CSVLine1.Source
$CSVTYPE1 = $CSVLine1.TYPE
$CSVMessage1 = $CSVLine1.Message
Write-Output -InputObject ('Changing {0} to {1}' -f $CSVLine1.gid, $CSVHold1)
}
Using your sample data, the above outputs:
C:> . 'C:\Powershell\Scripts\dchero.ps1'
Changing KLEMOE to KLE
Changing EEINGJ to EEI
Lastly, be aware that that the SubString method will fail if the length of $CSVLine1.GID is less than 3.

Log and read only last 10 minutes

I am begginer in Powershell and I have a problem with script.
I have a log and I need to send an email notification with an error. I would like to plan a task (TASK SCHEDULE) that will run my script regularly every ten minutes. This script verifies the last lines written in the last ten minutes. If the word ERROR is found, it will send an e-mail with this line where is the word ERROR.
My log:
2022-02-08 12:04:35,152 [105] ERROR RSeC.NET.RedundantHttpClient - No server found
2022-02-08 14:28:51,317 [4] DEBUG RSeC.NET.RSeC - Logging initialised
2022-02-08 14:28:53,835 [4] DEBUG RSeC.NET.JsonParser - Response binary data decoded. Size=424132
2022-02-08 14:29:20,494 [105] DEBUG RSeC.NET.RSeC - Logging initialised
2022-02-08 15:38:35,152 [105] ERROR RSeC.NET.RedundantHttpClient - No server found
2022-03-08 15:28:51,317 [4] DEBUG RSeC.NET.RSeC - Logging initialised
2022-03-08 15:28:53,835 [4] DEBUG RSeC.NET.JsonParser - Response binary data decoded. Size=424132
2022-03-08 15:39:20,494 [105] DEBUG RSeC.NET.RSeC - Logging initialised
2022-03-08 15:39:35,152 [105] ERROR RSeC.NET.RedundantHttpClient - No server found
My script :-(
$file = "C:\Soubory\esel.log"
$date = (Get-Date).AddDays(-50).Date
$cont = Get-Content -Path $file | Select-String -Pattern $date | Select-String "ERROR" | Measure-Object -line
Foreach-Object {
if ($cont -match "ERROR")
{
$kontent = Get-Content -Path $file | Select-String -Pattern $date | Select-String "ERROR" | Measure-Object -line
Write-Host $cont
}
else
{
#NOTING
}
}
Thank You for help
GILD
I think Lee_Dailey gave you the answer in his comment.
Simply figure out the worst-case scenario to read the bottom number of lines of the file, where you can be certain the last ten minutes are in there.
Then do:
$maxLines = 20 # just a guess here, but you can narrow the number of lines to read by trial and error
$lastTenMinutes = (Get-Date).AddMinutes(-10)
$errorLines = Get-Content -Path 'C:\Soubory\esel.log' -Tail $maxLines |
Where-Object { [datetime]($_ -split ',')[0] -gt $lastTenMinutes -and $_ -match 'ERROR' }
# test if there were error lines found
if (#($errorLines).Count) {
# send your email alert.
# If this email is in HTML format, use: $errorLines -join '<br>'
# if the email is plain text, join with newlines: $errorLines -join [environment]::NewLine
# for demo just output to console
Write-Host ("Errors found:`r`n{0}" -f ($errorLines -join [environment]::NewLine))
}
else {
Write-Host "No error lines found" -ForegroundColor Green
}
On my Dutch locale, [datetime]($_ -split ',')[0] parses the date correctly, but on your machine you may have to use [datetime]::ParseExact(($_ -split ',')[0], 'yyyy-MM-dd HH:mm:ss', $null)
It looks like a csv without the header, and I can compare the first column like it's a date and time, so:
import-csv log -header time,message |
where { (get-date).AddMinutes(-10) -lt $_.time -and
$_.message -match 'error' }
time message
---- -------
2022-03-09 10:11:35 152 [105] ERROR RSeC.NET.RedundantHttpClient - No server found
I would use the windows event log for easier filtering.
As I said in the comment on your question, "figure out what is the largest number of entries you could ever expect in 10 minutes". When you have that number, change the "20" in line "$MinLinesToGet = 20" in the code below to that value. Also, change the line "$MaxLengthOfALine = 100" so that it has the length of the longest line you expect to see.
If for some reason you need more than 10 minutes, change the value in the line "$MinutesOld = 10".
The code:
Uses ReadBytesFromFileEnd to read $ByteCount bytes from the end of $FilePath.
Uses ReadLinesFromFileEnd to read $MinLineCount of lines, each are expected to have less than $MaxLineLength, from the end of $FilePath. In reality, it should read several lines more than we want - which is a good thing.
Uses "[System.Text.Encoding]::UTF8.GetString" to convert the bytes to a string. And then uses Split to make an array of strings that is saved in $Lines.
The UTF8 before GetString is a type of encoding, and is the most likely file encoding the log file is in, so you shouldn't have to change anything. But, if there are problems, find the line "<## >" and remove the space when testing. The code will then give the raw text lines that are being returned by ReadLinesFromFileEnd. At that point, you can try the other encodings listed in the comment line above the GetString statement. Most encoding have a character size of 1, but in some unlikely, or absurd case where your log file has a larger character size, then change the line "$CharSize = 1" as needed.
You didn't provide your regex you were using, so I built my own and used the switch statement to loop through all the lines that are returned by ReadLinesFromFileEnd. I made the assumption that comma after the date WAS NOT part of a comma delimited line, but still part of the time stamp, and the numbers just afterwards is the milliseconds. I don't know what the numbers in the brackets are, so I just gave it the name "Code".
Those lines older than 10 minutes are used to build a PSObject that you can use in later code.
The last 3 lines are an example using the returned log entries in a Write-Host statement.
This worked well in my testing, but never know till the code is actually tried in the real world.
function ReadBytesFromFileEnd{
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$FilePath,
[Parameter(Mandatory = $true, Position = 1)]
[int]$ByteCount
)
$fs = [IO.File]::OpenRead($FilePath) # Open file
if($ByteCount -gt $fs.Length) {$ByteCount = $fs.Length} # Prevent reading more bytes than exist
$null = $fs.Seek(-$ByteCount, [System.IO.SeekOrigin]::End) # Position for reading
$Return = new-object Byte[] $ByteCount # Define the buffer $Return
$fs.Read($Return, 0, $ByteCount) | Out-Null # Fill the buffer
$fs.Close() # Close the file
return $Return
}
function ReadLinesFromFileEnd{
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$FilePath,
[Parameter(Mandatory = $true, Position = 1)]
[int]$MinLineCount,
[Parameter(Mandatory = $true, Position = 2)]
[int]$MaxLineLength
)
$CharSize = 1
[int]$ByteCount = 1.25 * ($MinLineCount + 1) * $MaxLineLength * $CharSize
# Encoding Options: ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7,UTF8
$null, $Return = [System.Text.Encoding]::UTF8.GetString((ReadBytesFromFileEnd $FilePath $ByteCount)).Split(#("`n","`r"),[System.StringSplitOptions]::RemoveEmptyEntries)
return $Return
}
$MinLinesToGet = 20
$MaxLengthOfALine = 100
$MinutesOld = 10
$Lines = ReadLinesFromFileEnd 'C:\Soubory\esel.log' $MinLinesToGet $MaxLengthOfALine
<## >
$Lines
exit
#>
$Now = Get-Date
$RecentLogs = switch -Regex ($Lines) {
'^(?<DateTime>\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d,\d+)\s*\[(?<Code>\d+)\]\s*(?<Description>.*)$' {
$DateTime = [DateTime]::ParseExact($Matches.DateTime, 'yyyy-MM-dd HH:mm:ss,fff', $null)
if ($Now.Subtract($DateTime).TotalMinutes -lt $MinutesOld) {
New-Object PSObject -Property #{
DateTime = $DateTime
Code = $Matches.Code
Description = $Matches.Description
}
}
continue
}
Default {
continue
}
}
$RecentLogs | ForEach-Object {
Write-Host "$($_.DateTime) [$($_.Code)] $($_.Description)"
}
EDIT:
You may want to check for lines that are not caught by the Regex. If so, place the following lines between the Default { statement and the coninue statement.
Write-Color "Regex failed to match: " -ForegroundColor Red -NoNewLine
Write-Color "$_" -ForegroundColor Yellow

Windows PowerShell: How to parse the log file?

I have an input file with below contents:
27/08/2020 02:47:37.365 (-0516) hostname12 ult_licesrv ULT 5 LiceSrv Main[108 00000 Session 'session1' (from 'vmpms1\app1#pmc21app20.pm.com') request for 1 additional licenses for module 'SA-XT' - 1 licenses have been allocated by concurrent usage category 'Unlimited' (session module usage now 1, session category usage now 1, total module concurrent usage now 1, total category usage now 1)
27/08/2020 02:47:37.600 (-0516) hostname13 ult_licesrv ULT 5 LiceSrv Main[108 00000 Session 'sssion2' (from 'vmpms2\app1#pmc21app20.pm.com') request for 1 additional licenses for module 'SA-XT-Read' - 1 licenses have been allocated by concurrent usage category 'Floating' (session module usage now 2, session category usage now 2, total module concurrent usage now 1, total category usage now 1)
27/08/2020 02:47:37.115 (-0516) hostname141 ult_licesrv CMN 5 Logging Housekee 00000 Deleting old log file 'C:\Program Files\PMCOM Global\License Server\diag_ult_licesrv_20200824_011130.log.gz' as it exceeds the purge threashold of 72 hours
27/08/2020 02:47:37.115 (-0516) hostname141 ult_licesrv CMN 5 Logging Housekee 00000 Deleting old log file 'C:\Program Files\PMCOM Global\License Server\diag_ult_licesrv_20200824_021310.log.gz' as it exceeds the purge threashold of 72 hours
27/08/2020 02:47:37.625 (-0516) hostname150 ult_licesrv ULT 5 LiceSrv Main[108 00000 Session 'session1' (from 'vmpms1\app1#pmc21app20.pm.com') request for 1 additional licenses for module 'SA-XT' - 1 licenses have been allocated by concurrent usage category 'Unlimited' (session module usage now 2, session category usage now 1, total module concurrent usage now 2, total category usage now 1)
I need to generate and output file like below:
Date,time,hostname,session_module_usage,session_category_usage,module_concurrent_usage,total_category_usage
27/08/2020,02:47:37.365 (-0516),hostname12,1,1,1,1
27/08/2020,02:47:37.600 (-0516),hostname13,2,2,1,1
27/08/2020,02:47:37.115 (-0516),hostname141,0,0,0,0
27/08/2020,02:47:37.115 (-0516),hostname141,0,0,0,0
27/08/2020,02:47:37.625 (-0516),hostname150,2,1,2,1
The output data order is: Date,time,hostname,session_module_usage,session_category_usage,module_concurrent_usage,total_category_usage.
Put 0,0,0,0 if no entry for session_module_usage,session_category_usage,module_concurrent_usage,total_category_usage
I need to get content from the input file and write the output to another file.
Update
I have created a file input.txt in F drive and pasted the log details into it.
Then I form an array by splitting the file content when a new line occurs like below.
$myList = (Get-Content -Path F:\input.txt) -split '\n'
Now I got 5 items in my array myList. Then I replace the multiple blank spaces with a single blank space and formed a new array by splitting each element by blank space. Then I print the 0 to 3 array elements. Now I need to add the end values (session_module_usage,session_category_usage,module_concurrent_usage,total_category_usage).
PS C:\Users\user> $myList = (Get-Content -Path F:\input.txt) -split '\n'
PS C:\Users\user> $myList.Length
5
PS C:\Users\user> $myList = (Get-Content -Path F:\input.txt) -split '\n'
PS C:\Users\user> $myList.Length
5
PS C:\Users\user> for ($i = 0; $i -le ($myList.length - 1); $i += 1) {
>> $newList = ($myList[$i] -replace '\s+', ' ') -split ' '
>> $newList[0]+','+$newList[1]+' '+$newList[2]+','+$newList[3]
>> }
27/08/2020,02:47:37.365 (-0516),hostname12
27/08/2020,02:47:37.600 (-0516),hostname13
27/08/2020,02:47:37.115 (-0516),hostname141
27/08/2020,02:47:37.115 (-0516),hostname141
27/08/2020,02:47:37.625 (-0516),hostname150
If you really need to filter on the granularity that you're looking for, then you may need to use regex to filter the lines.
This would assume that the rows have similarly labeled lines before the values you're looking for, so keep that in mind.
[System.Collections.ArrayList]$filteredRows = #()
$log = Get-Content -Path C:\logfile.log
foreach ($row in $log) {
$rowIndex = $log.IndexOf($row)
$date = ([regex]::Match($log[$rowIndex],'^\d+\/\d+\/\d+')).value
$time = ([regex]::Match($log[$rowIndex],'\d+:\d+:\d+\.\d+\s\(\S+\)')).value
$hostname = ([regex]::Match($log[$rowIndex],'(?<=\d\d\d\d\) )\w+')).value
$sessionModuleUsage = ([regex]::Match($log[$rowIndex],'(?<=session module usage now )\d')).value
if (!$sessionModuleUsage) {
$sessionModuleUsage = 0
}
$sessionCategoryUsage = ([regex]::Match($log[$rowIndex],'(?<=session category usage now )\d')).value
if (!$sessionCategoryUsage) {
$sessionCategoryUsage = 0
}
$moduleConcurrentUsage = ([regex]::Match($log[$rowIndex],'(?<=total module concurrent usage now )\d')).value
if (!$moduleConcurrentUsage) {
$moduleConcurrentUsage = 0
}
$totalCategoryUsage = ([regex]::Match($log[$rowIndex],'(?<=total category usage now )\d')).value
if (!$totalCategoryUsage) {
$totalCategoryUsage = 0
}
$hash = [ordered]#{
Date = $date
time = $time
hostname = $hostname
session_module_usage = $sessionModuleUsage
session_category_usage = $sessionCategoryUsage
module_concurrent_usage = $moduleConcurrentUsage
total_category_usage = $totalCategoryUsage
}
$rowData = New-Object -TypeName 'psobject' -Property $hash
$filteredRows.Add($rowData) > $null
}
$csv = $filteredRows | convertto-csv -NoTypeInformation -Delimiter "," | foreach {$_ -replace '"',''}
$csv | Out-File C:\results.csv
What essentially needs to happen is that we need to get-content of the log, which returns an array with each item terminated on a newline.
Once we have the rows, we need to grab the values via regex
Since you want zeroes in some of the items if those values don't exist, I have if statements that assign '0' if the regex returns nothing
Finally, we add each filtered item to a PSObject and append that object to an array of objects in each iteration.
Then export to a CSV.
You can probably pick apart the lines with a regex and substrings easily enough. Basically something like the following:
# Iterate over the lines of the input file
Get-Content F:\input.txt |
ForEach-Object {
# Extract the individual fields
$Date = $_.Substring(0, 10)
$Time = $_.Substring(12, $_.IndexOf(')') - 11)
$Hostname = $_.Substring(34, $_.IndexOf(' ', 34) - 34)
$session_module_usage = 0
$session_category_usage = 0
$module_concurrent_usage = 0
$total_category_usage = 0
if ($_ -match 'session module usage now (\d+), session category usage now (\d+), total module concurrent usage now (\d+), total category usage now (\d+)') {
$session_module_usage = $Matches[1]
$session_category_usage = $Matches[2]
$module_concurrent_usage = $Matches[3]
$total_category_usage = $Matches[4]
}
# Create custom object with those properties
New-Object PSObject -Property #{
Date = $Date
time = $Time
hostname = $Hostname
session_module_usage = $session_module_usage
session_category_usage = $session_category_usage
module_concurrent_usage = $module_concurrent_usage
total_category_usage = $total_category_usage
}
} |
# Ensure column order in output
Select-Object Date,time,hostname,session_module_usage,session_category_usage,module_concurrent_usage,total_category_usage |
# Write as CSV - without quotes
ConvertTo-Csv -NoTypeInformation |
ForEach-Object { $_ -replace '"' } |
Out-File F:\output.csv
Whether to pull the date, time, and host name from the line with substrings or regex is probably a matter of taste. Same goes for how strict the format must be matched, but that to me mostly depends on how rigid the format is. For more free-form things where different lines would match different regexes, or multiple lines makes up a single record, I also quite like switch -Regex to iterate over the lines.

Using -eq across two datasets in powershell

I'm in a juncture here. I have two datasets in powershell. Dataset 1($table) is received via an sql query (varies from 12 to 17 rows and has 8 columns) and Dataset 2($team) is hard coded in the script (has 18 rows and 2 columns). Both of these have a common column, Contest. Now the script I have to get working is - for each Contest in $table.contest, get other corresponding parameters from $table and match the Contest in $team.contest and get the corresponding $team.column2 value into play.
I'm able to get the data individually from each table, but when I use "-eq" condition across $table.contest & $team.contest, nothing happens.
This is the snippet from the code where I'm facing the problem.
$Contests = ($DataSet.Contest)
$Team = ($Team.cont)
foreach($Contest in $Contests)
{
$ContestName = $Contest
$stats = $DataSet | where {$_.contest -eq $contest}
$signups = $stats.SignUps
$newbies = $stats.Newbies
$uploads = $stats.Uploads
$views = $stats.Views
$eviews = $stats.EViews
$votes = $stats.Votes
$date = $stats.EndDate
$teamx = $team | where {$_ -eq $stats.contest}
$contest
$teamx
}
$contest shows the contest name, but $teamx is blank
The following is the changed code with respect hash tables. I tried to convert object array to string but in vain.
$team = #{
"Short Film" = "Member4";
"Student Photography" = "Member0";
"Student Art" = "Member1";
"Macro Photography" = "Member2";
"Landscape Photography" = "Member3";
}
$Contests = ($DataSet.Contest)
$Contests = $Contests | where {$_ -ne "" -and $_ -ne $null -and $_ -ne [dbnull]::value}
foreach($Contest in $Contests)
{
$ContestName = $Contest
$stats = $DataSet | where {$_.contest -eq $contest}
$signups = $stats.SignUps
$datatemp = $stats.Contest
if ($team.ContainsKey($datatemp)) {write-output "Exists"}
else {write-output "Doesn't Exist"}
$datatemp
$team.count
}
I tried directly feeding $Contest, $ContestName, and $stast.Contest inside ContainsKey, but all the time output is the same -
Doesn't Exist
Short Film
5
Doesn't Exist
Student Photography
5
Doesn't Exist
Student Art
5
Doesn't Exist
Macro Photography
5
Doesn't Exist
Landscape Photography
5
What am I doing wrong?
I can't tell for sure without knowing exactly what's in $Dataset, but your symptoms all point to trailing whitespace in the Contest value that's causing your tests to fail.
Try this and see if you get different results:
foreach($Contest in $Contests)
{
$ContestName = $Contest
$stats = $DataSet | where {$_.contest -eq $contest}
$signups = $stats.SignUps
$datatemp = $stats.Contest.trim()
if ($team.ContainsKey($datatemp)) {write-output "Exists"}
else {write-output "Doesn't Exist"}
$datatemp
$team.count
}