To complement helpful answer from Prateekshit Jaiswal with the truth about the -eq "True":
if it really concerns "a string that is returned from an api call", the extra -eq "True" is not an issue:
(although I would really recommend against adding that.)
if (".\controllers\myaction c:\test\path".ToLower().Contains("c:\") -eq "True") {
Write-Host 'code here'
}
code here
This is because PowerShell is a loosely typed language where the left-hand-side (LHS) of the condition dictates the comparison method. This means if the LHS is a boolean:
".\controllers\myaction c:\test\path".ToLower().Contains("c:\") -is [Bool]
True
The RHS is type casted to a Boolean:
[Bool]"True"
True
Because both sides are $True, the condition is simply considered $True (or truthy).
So what's really playing here?
I suspect that $result.context isn't really a string but something like an array of strings:
$result = @{ context = ".\controllers\myaction", "c:\test\path" }
$result.context
.\controllers\myaction
c:\test\path
Or :
"$($result.context)"
.\controllers\myaction c:\test\path
PowerShell's member-access enumeration is a nice feature but often makes things rather confusing:
if you use the .ToLower() (string) method on a string array, this will work wonder well:
$result.context.ToLower()
.\controllers\myaction
c:\test\path
But as the .Contains method is also a method of an array, you might see unexpected results for this method:
$result.context.ToLower().Contains("c:\")
False
This is because the array doesn't contain the (full) string "c:\". Where it does contain the string:
$result.context.ToLower().Contains("c:\test\path")
True
Note that there is actually no reason to use the .ToLower() method here as by default PowerShell does a case-insensitive compare.
Yet, this .ToLower() method might make things even more confusing as it "unrolls" any array with a single item to the item itself:
@{ context = @("c:\test\path") }.context.GetType().Name
Object[]
vs:
@{ context = @("c:\test\path") }.context.ToLower().GetType().Name
String
Which explains any unexpected result towards:
@{ context = @("c:\test\path") }.context.Contains("c:\")
False
vs:
@{ context = @("c:\test\path") }.context.ToLower().Contains("c:\")
True
Unfortunately, I can't give you an exact answer as I don't know the actual data type and structure of $result.context (you might consider to add the results of $result.context.GetType().Name and $result.context | ConvertTo-Json -Depth 9 to your question) but I hope that this might clear a few things with regards to the behavior of PowerShell related to your issue.
matchoperator? about_Comparison_Operators'.\controllers\myaction c:\test\path'.ToLower().Contains('c:\')istrue. Just remove-eq "True"from the condition.-eq "False"is the cause of the problem (because it is, in fact, the same as-eq $true(!), given that any nonempty string is coerced to$truein a Boolean context). By contrast, the-eq "True"used here - while unnecessary and conceptually misleading - is not the cause of the problem and incidental to the problem at hand, the latter being that$resultin actuality contains an array of strings, as explained in iRon's answer.$result -Match "c:\\"or similar. But again, it's just guesswork without the info.-eq "True"part is an incidental no-op here, unlike in the alleged duplicate), so I suggest retracting your close vote. As for the actual problem: That the presence of an array is the problem (which may apply to$resultand/or the.contextproperty value) is the only plausible explanation, and is also suggested by the fact that Kate accepted iRon's answer.