2010-05-28 14 views
6

Arrrg! Sto correndo in quello che sento è un problema stupido con una semplice sceneggiatura che sto scrivendo in PowerShell. Sto invocando un comando sql che chiama un proc memorizzato, con i risultati lo metto un array. I risultati sembrano qualcosa di simile:Perché non posso chiamare il metodo Contains dal mio array?

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

Quello che sto cercando di fare è if($s.Contains("Expired")), rapporto fallito. Semplice...? :(Problema in cui mi imbatto è che sembra che il metodo Contains non venga caricato quando ottengo un errore del genere:

Il richiamo del metodo non è riuscito perché [System.Object []] non contiene un metodo denominato ' contiene at line:. 1 char: 12 + $ s.Contains < < < < ("scaduto") + CategoryInfo: InvalidOperation: (contiene: String) [], RuntimeException + FullyQualifiedErrorId: methodNotFound

Quindi, cosa posso fare per fermare PowerShell dallo srotolarlo alla stringa? Script ps attuale sotto -

$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." 
} 

risposta

5

Il motivo per cui si vede Get-Members è che PowerShell sta cercando di essere utile e srotolare la raccolta. Se si dispone di un array con più tipi di elementi, mostra i membri per ciascun tipo (ad esempio se si è 'ls' (Get-ChildItem) e ci sono FileInfos e DirectoryInfos nella directory in cui ci si trova e si pipa ls | gm , che vi mostrerà i membri del FileInfos e anche un altro gruppo di membri del DirectoryInfos):

(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() 
… 

Cosa faccio di solito, per assicurarsi che io non sto guardando i membri srotolati, è cercare “$ s.GetType() .Nome "prima di vedere con cosa ho a che fare. Nel tuo caso, è chiaramente come array, poiché l'hai inizializzato come "$ s = @ (Invo" (il @ = è un array.)

Per sapere se un array contiene un elemento, puoi usare il - contiene operator:

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

Penso che hai un array di stringhe, quindi è possibile utilizzare una stringa letterale, come:

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

Ma se la scaduto non è una corrispondenza esatta (si cercavamo un elemento che fosse scaduto, come "Connection Expired 1/1/2010") devi trovare le corrispondenze e spuntare th e contare, penso:

(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 questo caso, non v'è solo una partita, in modo da PowerShell srotolato in una stringa. Cretino. Se ci sono più di 1 partite, tuttavia:

(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 

Ora è un array.

Fortunatamente, sia stringa e la matrice hanno una proprietà length:

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

modo da poter controllare la lunghezza dei vostri risultati che contengono “Scaduto” per vedere se ci sono di scaduto:

(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's expired, dog." } 
Whoas, shit's expired, dog. 

(forse qualcuno ha un modo migliore per verificare se una raccolta contiene un elemento che soddisfa un predicato (come LINQ's Any)?)

+0

Grazie Chris! Questo sicuramente mi ha portato nella giusta direzione. lo script di lavoro: $ s = @ (Invoke-Sqlcmd -Query "USO DB GO exec Monitor_TEST_ps 'EXPORT_RUN', NULL, 20" ' -ServerInstance "testdb002 \ testdb_002") if ($ s | {? $ _ ['Stato'] -eq 'OK'}) { Scrivi host "Scoperto scaduto, NON RIUSCITO." } else { Write-Host "Non trovato, OK." } – xbnevan

7

In poche parole, $ s è un array .NET (si l'uso di @() lo garantisce) e si sta tentando di richiamare un metodo (Contiene) che non esiste su questo tipo .NET.

Il modo più semplice per risolvere il problema è quello di utilizzare -contains operatore del PowerShell che ha i vantaggi di lavorare contro gli array direttamente e facendo caso insenstive paragona ad es .:

if ($s -contains 'expired') { ... } 
+0

Wow, potrei giurare che lo stanco. Mi sento stupido ora, grazie anche Keith che ha funzionato. w00t. – xbnevan

+1

Semplice e al punto. Esattamente quello di cui avevo bisogno. Stavo sviluppando su un sistema PS 3 quindi ho provato a eseguire il mio codice su PS 2. Ho ricevuto questo errore e questa è una soluzione semplice per risolvere il problema. –

Problemi correlati