define ARM Parameters Variables with Excel - powershell

I have a list of 34 VMs to build in Azure, there's 3 different sizes, and apart from the nic name and VM name they are pretty much identical but going into 3 different resource groups. So I thought create a an excel with three tabs each one with with all the same details, leaving out the nic name and VM name. Then I created 3 text files, one for each VM build, populated those with the name of the VMs (random names not sequential), and thought simples, use a foreach loop, for each of the vm list pointing to a different tab. However when I try to run the Powershell it just hangs, I think it's at the point where it does a convertTo-Json. Also while I'm struggling, every time I can cel teh deployment as it just hangs, it takes about 15 minutes for the console to be responsive again, is there a process in the background that causes it to hang?
Appreciate any thoughts or suggestions, even if there's a better way of doing it.
The powershell code is at:
Code:
function vmparam
{
$ws = $wb.Worksheets.Item($wsnumber)
$data = Get-Content -Path "$updatepath\vm.parameters.json" -raw | ConvertFrom-Json
$Row=2
$col=2
Write-Host "updating parameters" -ForegroundColor Cyan
$data.parameters.diskCount.value = $ws.Cells.Item($Row,$col).offset(2,0).Value()
$data.parameters.vmSize.value = $ws.Cells.Item($Row,$col).offset(3,0).Value()
$x = $ws.Cells.Item($Row,$col).offset(2,0).Value()
if ($x -eq "1")
{
$xlArray = $ws.Cells.Item($Row,$col).offset(4,0).Value()
[String[]]$val = $xlArray[0]
$data.parameters.diskSize.value = $val
}
elseif ($x -eq "2")
{
$xlArray = $ws.Cells.Item($Row,$col).offset(4,0).Value().Split(',')
[String[]]$val = $xlArray[0], ($xlArray[1]).TrimStart()
$data.parameters.diskSize.value = $val
}
$data.parameters.networkName.value = $ws.Cells.Item($Row,$col).offset(5,0).Value()
$data.parameters.networkResourceGroup.value = $ws.Cells.Item($Row,$col).offset(6,0).Value()
$data.parameters.subnetName.value = $ws.Cells.Item($Row,$col).offset(7,0).Value()
$data.parameters.vm01NicName.value = "$vm-nic1"
#$data.parameters.vm01IPAddress.value = $ws.Cells.Item($Row,$col).offset(13,0).Value()
$data.parameters.vm01VMName.value = $vm
$data.parameters.stdVMImagePublisher.value = $ws.Cells.Item($Row,$col).offset(11,0).Value()
$data.parameters.stdVMImageOffer.value = $ws.Cells.Item($Row,$col).offset(12,0).Value()
$data.parameters.stdWindowsOSVersion.value = $ws.Cells.Item($Row,$col).offset(13,0).Value()
$data.parameters.diagstorageAccountName.value = $ws.Cells.Item($Row,$col).offset(14,0).Value()
$data.parameters.diagResourceGroup.value = $ws.Cells.Item($Row,$col).offset(15,0).Value()
$data | ConvertTo-Json -Depth 9 | % { [System.Text.RegularExpressions.Regex]::Unescape($_) } | set-content -Path "$updatedpath\$vm.parameters.json"
Write-Host "parameters updated" -ForegroundColor Green
}
Thanks in advance :)

The error was related to the xls stored in onedrive and not locally.. :)

Related

SMLETS: Powershell

We want to generate an SR per row based on the criteria of a CSV file looking like:
SR templete
The additional criterion:
If the SLO countdown is less than 7 days then the due date is always 7 days for the ticket to be due. Otherwise then then countdown is number SLO _Countdown
The support group is always servicedesk
Unless the host_name does not contain "RES" then it is the support group is EITS_HW_Notes and it will be assigned to "custodian".
No matter what an SR is generated even if null.
My difficulty is my lack familiarity with smlets. I am happy to consider generating tickets via email as well. But would like help on how best to do that via powershell. But the code I came up with is below:
`#Prod
#$GLOBAL:smdefaultcomputer = "prodserver"
#Test
$GLOBAL:smdefaultcomputer = "testserver"
Import-Module SMlets
$path = "C:\Temp\Test.csv"
$csv = Import-csv -path $path
#Variable / Class Setup
$srClass = Get-SCSMClass -name System.WorkItem.ServiceRequest
$srprior = Get-SCSMEnumeration -Name ServiceRequestPriorityEnum.Medium
$srurg = Get-SCSMEnumeration -Name ServiceRequestUrgencyEnum.Medium
#$ararea = get-SCSMEnumeration -Name ServiceRequestAreaEnum.Other
$ararea = get-SCSMEnumeration -Name Enum.add3768303064ec18890170ba33cffda
$title = “Title Goes Here”
$descrip = "Description info goes here"
#Service Request Arguements
$srargs = #{
Title = $title;
Urgency = $srurg;
Priority = $srprior;
ID = “SR{0}”;
Area = $ararea;
SupportGroup = "ServiceDesk";
Description = $descrip
}
#Create Service Request
$newServiceRequest = New-SCSMOBject -Class $srClass -PropertyHashtable $srargs -PassThru
#get SR ID of the new object
$SRId = $newServiceRequest.id
#Get Projection & Object for Created Service Request
$srTypeProjection = Get-SCSMTypeProjection -name System.WorkItem.ServiceRequestProjection$
$SRProj = Get-scsmobjectprojection -ProjectionName $srTypeProjection.Name -filter “Id -eq $SRId”
#Set Afffected User
$userClass = Get-SCSMClass -Name Microsoft.AD.UserBase$
$cType = "Microsoft.EnterpriseManagement.Common.EnterpriseManagementObjectCriteria"
$cString = "UserName = 'itservicenotifications' and Domain = 'SHERMAN'"
$crit = new-object $cType $cString,$userClass
$user = Get-SCSMObject -criteria $crit
$AffectedUserRel = get-scsmrelationshipclass -name System.WorkItemAffectedUser$
New-SCSMRelationshipObject -RelationShip $AffectedUserRel -Source $newServiceRequest -Target $user -Bulk`
I tried the above code but am running into issues recognizing the column name in the CSV file and am unfamiliar with SMLETS + powershell if statements.
Columns are:
CSV Columns
CSV text with examples is: Columns with examples
Could you paste the CSV columns as text, please? Or, better, a sample CSV with one or two rows (redact any sensitive data).
I would expect a CSV to contain multiple rows - even if yours does not, it's good defensive programming to act as if it does. So the first modification I suggest is:
$path = "C:\Temp\Test.csv"
$csv = Import-csv -path $path
foreach ($Row in $csv)
{
# the rest of your code goes in here
}
I find it helpful while debugging to go step-by-step. If I understand your problem right, it's about building the right hashtable in $srargs to pass to New-SCSMOBject. So the next modification is:
foreach ($Row in $csv)
{
$srClass = Get-SCSMClass -name System.WorkItem.ServiceRequest
# etc
$srargs = #{
Title = $title
Urgency = $srurg
Priority = $srprior
ID = “SR{0}”
Area = $ararea
SupportGroup = "ServiceDesk"
Description = $descrip
}
$srargs # write the hashtable so you can inspect it
# skip the rest of the code for now
}
I understand your question as "how to express the logic of":
support group is always servicedesk
Unless the host_name does not contain "RES"
then the support group is contents of EITS_HW_Notes cell in CSV
and it will be assigned to "custodian"
I can't help you with setting the assignee. But we can rejig the rest of the statement:
if host_name contains "RES"
SupportGroup = servicedesk
else
SupportGroup = contents of EITS_HW_Notes cell
You can code that like this:
foreach ($Row in $csv)
{
$srClass = Get-SCSMClass -name System.WorkItem.ServiceRequest
# etc
if ($Row.host_name -like "*RES*")
{
$SupportGroup = "ServiceDesk"
}
else
{
$SupportGroup = $Row.EITS_HW_Notes
}
$srargs = #{
Title = $title
# etc
SupportGroup = $SupportGroup
Description = $descrip
}
}
Does that get you any closer to your solution?

Issue with moving multiple items from one outlook folder to another - Powershell

I am trying to select multiple emails from on outlook inbox folder via mapi addressing and want to move a copy of these emails to another folder in the same inbox.
Unfortunately my script seems to do whatever it wants, sometimes copying 6 emails before stopping with following failure, sometimes stopping right with the first email.
Failure:
... "veeam")} | ForEach-Object {$_.Copy().Move($Namespace.Folders.Item("$ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [ForEach-Object], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.PowerShell.Commands.ForEachObjectCommand
I could not find any solution for this and I am sitting here confused since in another mailbox the code works just fine.
Of course I am setting the variables $Mailbox and $TempWorkPath beforehand.
Thanks in advance for your help.
Trying to run the code in a foreach-loop is less performant and ends with the same issue.
About 3 hours of google search did not help me at all.
Just moving the object causes the code to break, probably because of indexiation?
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
$OutlookSession = New-Object -ComObject Outlook.Application
$Namespace = $OutlookSession.GetNameSpace("MAPI")
$Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Items.Restrict('[UnRead] = True') | Where-Object {($_.Subject -match "ackup") -or ($_.SenderEmailAddress -match "veeam")} | ForEach-Object {$_.Copy().Move($Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Folders.Item("$TempWorkPath"))} | Out-Null
<# Do things with the selected/coppied emails #>
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($OutlookSession) | Out-Null
$OutlookSession = $null | Out-Null
In Theory an based on my tests in another folder this should work perfectly fine, create a copy of the email, move it to my folder and afterwards I can do things with it.
Well, I think I found my way around the issue. Running the command in a while loop instead of an foreach loop seems to work better.
$Inbox = $Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Items.Restrict('[UnRead] = True') | Where-Object {($_.Subject -match "ackup") -or ($_.SenderEmailAddress -match "veeam")}
$MailCounter = $Inbox.Count
$HelperForCounting = 0
while ($MailCounter -gt $HelperForCounting)
{
$Inbox[$MailCounter].Copy().Move($Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Folders.Item("$TempWorkPath"))
$MailCounter = $MailCounter - 1
}
Greetings
I also had this issue with processing emails on Outlook. My overall scheme is to process emails folder by folder. I traced the issue to the Emails.getNext() function. My completely uneducated guess is it has something to do with parallel processing of Emails and how it grabs them in ForEach() and getNext(). The problem went away by using the getLast().
Note in the following code it will just move all read emails to archive folder and then some unread emails to corporate dump folder and most unread emails to the unread folder. This is itself just a mutation on the .p0r email script. There is a > $null at the end of the function block is where I originally had it on the ForEach loop and it worked as one would expect, but it does not work on the While loop blocking function. Instead that had to be moved to the location in the move unread section. Still a lot of room for improvement, getting some strange com errors but it will process through an inbox so long as GetLast() email is moved out of the folder.
As for my rationale on the root cause, I noticed that the failure to read a whole inbox is dependent on the size of the inbox. So each run my go through 2/3 of the remaining emails in the inbox.
# OUTLOOK RULES #
#################
# OUTLOOK RULES #
#################
#Import Object Library?
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
# VARIABLES
$index=0;
$pstPath = "C:\YOURPATHHERE"
# DISPLAY INFO
function display( [string]$subject, [string]$color , [string]$out) {
# REQUIRED LENGTH OF STRING
$len = 20
# STRINGS THAT ARE LONGER WILL BE CUT DOWN,
# STRINGS THAT ARE TO SHORT WILL BE MADE LONGER
if ( $subject.length -lt 20 ){
$toadd=20-$subject.length;
for ( $i=0; $i -lt $toadd; $i++ ){
$subject=$subject+" ";
}
$len = $subject.length
}
else { $len = 20 }
$index=$index+1
Write-host -ForegroundColor $color -nonewline " |" ((($subject).ToString()).Substring(0,$len)).ToUpper()
}
# CREATING OUTLOOK OBJECT
$outlook = New-Object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
# GETTING PST FILE THAT WAS SPECIFIED BY THE PSTPATH VARIABLE
$pst = $namespace.Stores | ?{$_.FilePath -eq $pstPath}
# ROOT FOLDER
$pstRoot = $pst.GetRootFolder()
# SUBFOLDERS
$pstFolders = $pstRoot.Folders
$fArchive = $pstFolders.Item("Archive")
# PERSONAL SUBFOLDER
$personal = $pstFolders.Item("Personal")
# INBOX FOLDER
$DefaultFolder = $namespace.GetDefaultFolder(6)
# INBOX SUBFOLDERS
$InboxFolders = $DefaultFolder.Folders
# DELETED ITEMS
$DeletedItems = $namespace.GetDefaultFolder(3)
# EMAIL ITEMS
$Emails = $DefaultFolder.Items
$workingFile = [IO.Path]::GetTempFileName()
# PROCESSING EMAILS
$currentWriteFolder = $pstFolders.Item("Archive")
While ($Emails.count -gt 0) {
$Email = $Emails.GetLast()
#Move all reads into Archive
if (!$Email.Unread) {
$email.move($fArchive) > $null
continue
}
#Filter unread items by sender
$WriteString = $Email.SenderEmailAddress.ToString()
[IO.File]::WriteAllLines($workingFile, $WriteString)
if (Select-String -Path $workingFile -Pattern "company") {
$email.move($currentWriteFolder.Folders.Item("globalcorp"))
continue
}
$email.move($pstFolders.Item("Unread"))
} # > $null
[IO.File]::Delete($workingFile)
Write-host ""

Output of Get-content as variable?

I am attempting to run a foreach loop on a get-content and convertfrom-json cmd. Now im aware this potentially has issues being multiple value results in the variable, im wondering how i can continue to pass this info to the rest of the script.
$testconv = Get-device * |select ID
$testid = $testconv.id
$conv = foreach ($id in $testid)
{
get-content "\\HDC-PRTG-03\System Information Database\Services\Device$id.Services" | Convertfrom-json
}
$rpccheck =$conv.message
$snmpcheck = $conv.message
$svcname = $conv.data.displayname
$svcstate=$conv.data.properties.state
if($RPCon = $rpccheck |select-string -pattern RPC -AllMatches){
write-host RPC Not enabled
}else{
write-host No RPC Enabled - Moving to Services List
Now when i run that with out the $conv= making it a variable it returns
kind : Services
recievetime : 29-01-2018 14:43:32
error : 106
Message : SNMP Channels Not Available.
Which is what i expect. However when i define it a variable with $conv= it just starts to say it cannot find the file paths which i find an odd error to throw but hey ho.
Do any of you smart guys have any pointers for how i can keep these fromjson objects in memory so i can continue to run foreach loops against them. The ultiumate function of this script is to query a local .services file for what services are running on the device and then create sensors to monitor them within our PRTG installation. Therefore i need to be able to ref the deviceID and apply things to it.
I suspect i may be using too many foreach loops in the whole script but frankly i am 100% out of my depth
any guidance hugely hugely appreciated
Sam
If i understand correctly you should have json files for all device ID's. If a file with the name of a particular device is missing you will get the 'File not found' error.
As for the code, you can try this:
$testconv = Get-Device * | select ID
$testid = $testconv.id
$oldErrorAction = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
foreach ($id in $testid) {
try {
$conv = Get-Content -Path "\\HDC-PRTG-03\System Information Database\Services\Device$id.Services" -Raw | ConvertFrom-Json
$rpccheck = $conv.message # These look the same to me...
$snmpcheck = $conv.message # These look the same to me...
$svcname = $conv.data.displayname
$svcstate = $conv.data.properties.state
$Matches = ($rpccheck | Select-String -Pattern "RPC*" -AllMatches)
if ($Matches.Matches.Count) {
Write-Host "RPC Not enabled"
}
else {
Write-Host "No RPC Enabled - Moving to Services List "
}
}
catch {
Write-Warning $_.Exception.Message
}
}
$ErrorActionPreference = $oldErrorAction
Instead of the try{}..catch{} you could also first test if a file with that name is present using Test-Path directly before doing the Get-Content.

Powershell script exits ForEach-Object loop prematurely [duplicate]

This question already has answers here:
Why does 'continue' behave like 'break' in a Foreach-Object?
(4 answers)
Closed 5 years ago.
So I've been writing a script that will take all of the data that is stored in 238 spreadsheets and copy it into a master sheet, as well as 9 high level report sheets. I'm really not sure why, but after a specific document, the script ends prematurely without any errors being posted. It's very strange. I'll post some anonymized code below so maybe someone can help me find the error of my ways here.
As far as I can tell, the document that it exits after is fine. I don't see any data errors in it, and the info is copied successfully to the master document before powershell just calls it quits on the script completely.
I've tried changing the size of the data set by limiting only to the folder that contains the problem file. It still ends after the same file with no error output. I cannot upload the file due to company policy, but I really don't see anything different about the data on that one file when compared to any other file of the same nature.
Also, apologies in advance for the crappy code. I'm not a developer and have been relearning powershell since it's the only tool available to me right now.
$StartTime = Get-Date -Format g
Write-Host $StartTime
pushd "Z:\Shared Documents\IO"
$TrackTemplate = "C:\Users\USERNAME\Desktop\IODATA\MasterTemplate.xlsx"
# Initialize the Master Spreadsheet
$xlMaster = New-Object -ComObject Excel.Application
$xlMaster.Visible = $False
$xlMaster.DisplayAlerts = $False
$MasterFilePath = "C:\Users\USERNAME\Desktop\IODATA\Master.xlsx"
Copy-Item $TrackTemplate $MasterFilePath
$wbMaster = $xlMaster.Workbooks.Open($MasterFilePath)
$wsMaster = $wbMaster.Worksheets.Item(2)
$wsMaster.Unprotect("PASSWORD")
$wsMasterRow = 3
# Initialize L4 Document Object
$xlL4 = New-Object -ComObject Excel.Application
$xlL4.Visible = $False
$xlL4.DisplayAlerts = $False
# Initialize object for input documents
$xlInput = New-Object -ComObject Excel.Application
$xlInput.Visible = $False
$xlInput.DisplayAlerts = $False
# Arrays used to create folder path names
$ArrayRoot = #("FOLDER1","FOLDER2","FOLDER3","FOLDER4","FOLDER5","FOLDER6","FOLDER7","FOLDER8","FOLDER9")
$ArrayShort = #("SUB1","SUB2","SUB3","SUB4","SUB5","SUB6","SUB7","SUB8","SUB9")
# $counter is used to iterate inside the loop over the short name array.
$counter = 0
$FileNumber = 0
$TotalFiles = 238
$ArrayRoot | ForEach-Object {
$FilePathL4 = "C:\Users\USERNAME\Desktop\IODATA\ROLLUP\" + $ArrayShort[$counter] + "_DOC_ROLLUP.xlsx"
Copy-Item $TrackTemplate $FilePathL4
$wbL4 = $xlL4.Workbooks.Open($FilePathL4)
$wsL4 = $wbL4.Worksheets.Item(2)
$wsL4.Unprotect("PASSWORD")
$wsL4Row = 3
If ($ArrayShort[$counter] -eq "SUB7") {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\" + $ArrayShort[$counter] + " - DOC v2\"}
Else {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\!" + $ArrayShort[$counter] + " - DOC v2\"}
Get-ChildItem -Path $FilePath | ForEach-Object {
If ($_.Name -eq "SPECIFIC_DOC.xlsx") {Continue}
$FileNumber += 1
Write-Host "$FileNumber / $TotalFiles $_"
$wbInput = $xlInput.Workbooks.Open($_.FullName)
$wsInput = $wbInput.Worksheets.Item(2)
$wsInputLastRow = 0
#Find the last row in the Input document
For ($i = 3; $i -le 10000; $i++) {
If ([string]::IsNullOrEmpty($wsInput.Cells.Item($i,1).Value2)) {
$wsInputLastRow = $i - 1
Break
}
Else { Continue }
}
[void]$wsInput.Range("A3:AC$wsInputLastRow").Copy()
Start-Sleep -Seconds 1
[void]$wsMaster.Range("A$wsMasterRow").PasteSpecial(-4163)
Start-Sleep -Seconds 1
$wsMasterRow += $wsInputLastRow - 2
[void]$wsL4.Range("A$wsL4Row").PasteSpecial(-4163)
Start-Sleep -Seconds 1
$wsL4Row += $wsInputLastRow - 2
$wbInput.Close()
$wbMaster.Save()
}
$counter += 1
$wsL4.Protect("PASSWORD")
$wbL4.Save()
$wbL4.Close()
}
$wsMaster.Protect("PASSWORD")
$wbMaster.Save()
$wbMaster.Close()
$xlMaster.Quit()
$EndTime = Get-Date -Format g
$TimeTotal = New-Timespan -Start $StartTime -End $EndTime
Write-Host $TimeTotal
To continue pipeline processing with the next input object, use return - not continue - in the script block passed to the ForEach-Object cmdlet.
The following simple example skips the 1st object output by Get-ChildItem and passes the remaining ones through:
$i = 0; Get-ChildItem | ForEach-Object{ if ($i++ -eq 0) { return }; $_ }
There is currently (PSv5.1) no direct way to stop the processing of further input objects - for workarounds, see this answer of mine.
By contrast, as you've discovered, break and continue only work as expected in the script block of a for / foreach statement, not directly in the script block passed to the ForeEach-Object cmdlet:
For instance, the following produces no output (using break would have the same effect):
$i = 0; Get-ChildItem | ForEach-Object{ if ($i++ -eq 0) { continue }; $_ }
The reason is that continue and break look for an enclosing for / foreach statement to continue / break out of, and since there is none, the entire command is exited; in a script, the entire script is exited if there's no enclosing for / foreach / switch statement on the call stack.

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
}