tags:

views:

66

answers:

1

I'm trying to write a small Powershell function that will return some summary data from some XML log files. I wrote a short summarizing function:

function Summarize-Log( $log )
{
   $obj = New-Object Object
   $obj | Add-Member NoteProperty Date $log.lastwritetime 
   $obj | Add-Member NoteProperty Passed ([xml](get-content $log)).suite.passed
   $obj | Add-Member NoteProperty NotImplemented ([xml](get-content $log)).suite.notImplemented

   return $obj
}

I think I should be able to call this function like this:

dir -recurse $logDirs | where { $_.name -eq "MyLog.xml" } | foreach{ Summarize-Log $_ }

When I call it like this, it seems to read the SAME numbers out of each pass through the loop. The Date property is correct, but the two properties being read from the XML are incorrect, as if the get-content call is returning the same data regardless of the input parameter.

How do I fix this?

Right now it appears from the code as if the whole file will be read in twice. Is there a more efficient way to get this information?

+1  A: 

Your script looks fine. Are you sure that the dir|where command is actually returning different mylog.xml files?

To not re-read the xml, cache the xml in a variable in your function:

function Summarize-Log( $log ) 
{ 
   $xml = [xml](get-content $log)

   $obj = New-Object pscustomobject
   $obj | Add-Member NoteProperty Date $log.lastwritetime  
   $obj | Add-Member NoteProperty Passed $xml.suite.passed 
   $obj | Add-Member NoteProperty NotImplemented $xml.suite.notImplemented 

   $obj
} 

Also, try to get out of the habit of using the return keyword (i've removed it from my rewrite) as any value that is not explicitly captured by assignment to a variable will be returned from the function.

edit: use $.fullname instead of $ as $_.tostring() (which is implied) will resolve to filename only, not path+name.

dir -rec | foreach { summarize-log $_.fullname }
x0n
I am sure. I misspoke when I said the $log var wasn't being updated, as the Date property changes for each file. But the two properties that are being read from the Xml are the same each time. But if I call the function directly, passing it a given log, the numbers are correct.
Ben Fulton
That doesn't make much sense - there's obviously more to this script that you're showing. Can you paste the rest? Double-check that $logdirs is what you think it is - my money is on it containing the same directory multiple times.
x0n
No. The error is clearly in the dir | where section; if I writedir -recurse foo | where { $_.name -eq "Test1.txt" } | foreach { get-content $_ }it fails with an error for each file named Test1.txt in the tree. But, if there is a file named Test1.txt in the current directory, the content is read from THAT file each time. I'm still figuring out a workaround.
Ben Fulton
ah, I know what this is - this is problem with .NET - FileInfo.ToString() returns different values depending on which constructor you use. Make sure you pass $_.fullname to summarize-log, not $_ as this will fall foul of the gotcha. It's not a ppowershell problem.
x0n
That seems to do it. A final change is in the Date getter, which is now no longer getting a fileinfo directly. So that line becomes$obj | Add-Member NoteProperty Date (get-item $log).lastwritetime
Ben Fulton