Why can't I call the Contains method from my array?

Arrrg! I am facing what, in my opinion, is a dumb problem with a simple script that I write in powershell. I call the sql command, which calls the stored procedure, with the results I put it in an array. The results look something like this:

Status ProcessStartTime ProcessEndTime ------ ---------------- -------------- Expired May 22 2010 8:31PM May 22 2010 8:32PM 

What I'm trying to do is if($s.Contains("Expired")) , the report failed. Just ...? :( The problem I am facing is: the Contains method does not load, since I get this error:

Method call failed because [System.Object []] does not contain a method named "Contains". On line: 1 char: 12 + $ s.Contains <<("Expired") + CategoryInfo: InvalidOperation: (contains: String) [], RuntimeException + FullyQualifiedErrorId: MethodNotFound

So what can I do to stop powershell from expanding it to a string? Actual ps script below -

 $s = @(Invoke-Sqlcmd -Query "USE DB GO exec Monitor_TEST_ps 'EXPORT_RUN',NULL,20" ` -ServerInstance testdb002\testdb_002 ) if ($s.Contains("Expired")) { Write-Host "Expired found, FAIL." } else { Write-Host "Not found, OK." } 
+6
powershell
source share
2 answers

The reason you see the Get-Members method is because powershell is trying to be useful and expand the collection. If you have an array with several types of elements, it shows you members for each type (for example, if you are ls (Get-ChildItem), and the directory you are in has FileInfos and DirectoryInfos, and you use ls | gm, it will show you the members of FileInfos, as well as another group of DirectoryInfos members):

 (7) C:\ -» ls Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 5/28/2010 8:19 AM .hg d---- 5/13/2010 3:37 PM Build … -a--- 4/22/2010 11:21 AM 2603 TODO.org (8) C:\ -» ls | gm TypeName: System.IO.DirectoryInfo Name MemberType Definition ---- ---------- ---------- Mode CodeProperty System.String Mode{get=Mode;} Create Method System.Void Create(System.Security.AccessControl.Direct... … TypeName: System.IO.FileInfo Name MemberType Definition ---- ---------- ---------- Mode CodeProperty System.String Mode{get=Mode;} AppendText Method System.IO.StreamWriter AppendText() … 

What I usually do to make sure that I don't look at the expanded members is try $ s.GetType (). Call it first to find out what I mean. In your case, this is clear and an array, since you initialized it as "$ s = @ (Invo" (@ = its array.)

To find out if an array contains an element, you can use the -contains operator:

 (9) C:\ -» @(1,2,3) -contains 1 True 

I think you have an array of strings, so you can use a string literal, for example:

 (10) C:\ -» @("Stuff","you've","got","might have","Expired") -contains "Expired" True 

But if expired is not an exact match (you were looking for the item you are looking for, for example, “Connection Expired 1/1/2010”), you need to find matches and check the quantity, I think:

 (23) C:\ -» @("Stuff","you've","got","might have","Connection Expired 1/1/2010") -contains "Expired" False (24) C:\ -» @("Stuff","you've","got","might have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")} Connection Expired 1/1/2010 (33) C:\ -» $xs = @("Stuff","you've","got","might have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")} (34) C:\ -» $xs.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object (35) C:\ -» $xs Connection Expired 1/1/2010 

In this case, there is only one match, so powershell expands it into a string. Moron. If there are more than 1 matches, then:

 (36) C:\ -» $xs = @("Stuff","you've","got","might Expired have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")} (37) C:\ -» $xs.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array (38) C:\ -» $xs might Expired have Connection Expired 1/1/2010 

Now its an array.

Fortunately, both the string and the array have the length property:

 (39) C:\ -» $xs.Length 2 (40) C:\ -» "Bob".Length 3 

So, you can check the length of your results that contain "Expired" to find out if the validity period has expired:

 (41) C:\ -» $xs = @("Stuff","you've","got","might Expired have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")} (42) C:\ -» if ($xs.Length -gt 0) { Write-Host "Whoas, stuff expired, dog." } Whoas, shit expired, dog. 

(maybe someone has a better way to check if the collection contains an element that satisfies some predicates (e.g. LINQ Any)?)

+5
source share

Simply put, $ s is a .NET array (you use @() ), and you are trying to call a method (Contains) that does not exist in this .NET type.

The easiest way to solve your problem is to use the PowerShell -contains , which has the advantages of working with arrays directly and comparing case-insenstive, for example:

 if ($s -contains 'expired') { ... } 
+7
source share

All Articles