Question

I have just started PowerShell today I have this type of log files with any number of tests:

Plan test.pln - 1 error

    [#VERSION-TestPlanGenerator#]3.8.0.0018
    HW# VS4_1
    [#TC#] test 1
        \\APPS-EUAUTO1\C$\...\Temp\FXSAPIDebugLogFile.txt - The process cannot access the file because it is being used by another process.
        [APPS-EUAUTO1] [prep] Setting agent options and random seed...
        [APPS-EUAUTO1] [info] Initial Seed : 124426621
        [APPS-EUAUTO1] [info] Current seed : 96010
        [APPS-EUAUTO1] [info] rt1 t1
        [APPS-EUAUTO1] [debug] rt1 t1
        [#WARNING#][APPS-EUAUTO1] [warning] rt1 t1 ( Screen shot : D:\...\[APPS-EUAUTO1] 03-28-14 11-29-22.png)
        [#WARNING#][APPS-EUAUTO1] [warning] Unhandled error detected ! ( Screen shot : D:\...\[APPS-EUAUTO1] 03-28-14 11-29-22.png)
        [#ERROR#][APPS-EUAUTO1] [error] rt1 t1 ( Screen shot : D:...\[APPS-EUAUTO1] 03-28-14 11-29-22.png)
        Occurred in fnMsg at ..\functions\f_common.inc(456)
        Called from t1 at test.t(10)
        Called from rt1 at test.t(5)
    [#TC#] test 2
        [APPS-EUAUTO1] [prep] Setting agent options and random seed...
        [APPS-EUAUTO1] [info] Current seed : 177041
        [APPS-EUAUTO1] [info] rt2 t2
        [APPS-EUAUTO1] [debug] rt2 t2

I need to get all the tests in an array in witch each element will have:

  • a string Name ( ex: test 1)
  • a boolean Error (ex: true for test 1 because there is a [#WARNING#] or a [#ERROR#] message present)
  • a array Messages with all the messages (ex: for test 2 all 4 messages)

and at the end I will like to export this array to a html file.

All tests begins with [#TC#]. I'm having problems with the reading part. I have tried a couple of things from different sites but, it doesn't not seem to work for me :

Function Import-MyLog1 {
    # -----------------------------------------------------------------------
    Function Get-Log {
    # Reads the log file into memory.
        Try {
            Get-Content -path "res.txt" -ErrorAction Stop -Delimiter "[#TC#]"
        }
        Catch {
            Write-Error "The data file is not present" 
            BREAK
        }
    } # End: Function Get-Log
    # -----------------------------------------------------------------------
    Function Get-Record {
    Param ($Log)
        for ($i=1; $i -lt $Log.Length; $i++) { # ignore the header
            $Testcase = $Log[$i]
            New-Object PSobject -Property @{
                Name = $Testcase[0]
                Data = $Testcase[3..6]
            }
        }
    } # End: Function Get-Record
    # Load the log into memory
    $Log = Get-Log
    $Records = Get-Record -Log $Log
    $Records # Added only to see the current progress. 
} #End: Function Import-MyLog1

clear
Import-MyLog1

this is the final code for who might need a example :

Function Get-TxtLog {
Param ($File)
# Reads the log file into memory.
    Try {
        Get-Content -path $File -ErrorAction Stop -Delimiter "[#TC#]"
    } Catch {
        Write-Error "The data file is not present" 
        BREAK
    }
} # End: Function Get-TxtLog

# -----------------------------------------------------------------------

Function Get-Testcase {
Param ($TxtLog)
    for ($i=1; $i -lt $TxtLog.Count; $i++) { # $i=1 to ignore the header
        $Testcase = $TxtLog[$i].split("`n")
        $Output = New-Object PSobject -Property @{
            Name     = $Testcase[0].Trim()
            Messages = $Testcase[1..($Testcase.count)] | ?{!($_ -match "\[#TC#]")} | ForEach-Object -process {$_.Trim()}
        }
        $Error = $( if($Output.Messages -match ("\[#ERROR#]|\[#WARNING#]")) {$true} else {$false} )
        $Output|Add-Member -MemberType NoteProperty -Name "Error" -value $Error
        $Output|Add-Member -MemberType NoteProperty -Name "Runtime" -value $null # will be added later
        $Output|Add-Member -MemberType NoteProperty -Name "Data" -value $null    # will be added later
        $Output # to pipe the object
    }
} # End: Function Get-Testcase

# -----------------------------------------------------------------------

# Load the log into memory
$TxtLog = Get-TxtLog -file "D:\XHostMachine\Results\res.txt"
$Records = Get-Testcase -TxtLog $TxtLog
$Records | Format-Table
Was it helpful?

Solution

If you just started PowerShell today then I can only imagine what you'll be doing with it in a year's time... You have started very well in my opinion.

Now, you seem to want to make everything into a function, which I suppose there is little harm in, but personally it seems overkill. When I pasted your test code into my ISE the first thing I did was comment out the first line and 28th line through the end of it. There just doesn't seem to be a need for all that.

Next I added a parameter to the Get-Log function so that a path can be provided if desired, and if excluded it will default to your res.txt file.

Function Get-Record {
Param ($Log)
    for ($i=1; $i -lt $Log.Count; $i++) { # ignore the header
        $Testcase = $Log[$i].split("`n")
        $Output = New-Object PSobject -Property @{
            Name = $Testcase[0]
            Data = $Testcase[3..($Testcase.count)]|?{!($_ -match "\[#TC#]")}
            }
        $Output|Add-Member -MemberType NoteProperty -Name "Error" -value $(if($Output.data -match "^.+?(\[#ERROR#]|\[#WARNING#])"){$true}else{$false})
        $Output
    }
} # End: Function Get-Record

After that I looked at the value of $Log once it was gotten. You end up with an array with 3 strings in it. That's all fine and good, but what you really want is an array with 3 arrays in it if you ask me. Right now $Log[0] is a string with 4 lines of text, and you'd be better off with an array of 4 strings... so let's go that route first. I modified your Get-Record to accomplish that.

Function Get-Record {
Param ($Log)
    for ($i=1; $i -lt $Log.Count; $i++) { # ignore the header
        $Testcase = $Log[$i].split("`n")

You'll notice the split is done on n which is the powershell NewLine character. Then I updated the object you created to exclude the [#TC#] which was used as a delimiter, and assigned it a variable instead of just outputting it. Once I had that $Output variable I tested it for[#ERROR#]and[#WARNING#]` using a regex match and added a new Error property to the object depending on if an error was found or not.

        $Output = New-Object PSobject -Property @{
            Name = $Testcase[0]
            Data = $Testcase[3..($Testcase.count)]|?{!($_ -match "\[#TC#]")}
            }
        $Output|Add-Member -MemberType NoteProperty -Name "Error" -value $(if($Output.data -match "^.+?(\[#ERROR#]|\[#WARNING#])"){$true}else{$false})
        $Output
    }
} # End: Function Get-Record

Then I pretty much passed the rest off as is except added my path to the log that I made from your example text.

# Load the log into memory
$Log = Get-Log c:\temp\test.log
$Records = Get-Record -Log $Log
$Records # Added only to see the current progress. 
#} #End: Function Import-MyLog1
#
#clear
#Import-MyLog1

Now, you could clean it up a bit I suppose by trimming blank space from the beginning of lines if you wanted, but that's just a matter of taste. But it gives you 2 entries in $Records each with the name you wanted, and the data lines, and a boolean Error property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top