Reading text file that is not really text

This topic contains 0 replies, has 1 voice, and was last updated by Profile photo of Forums Archives Forums Archives 5 years, 3 months ago.

  • Author
    Posts
  • #5791

    by Lery at 2013-04-10 12:36:33

    Here is a good one for you all. I'm not sure I understand why the software developer did this, but I'm sure they must have a good reason. I'm reading the content of a text file. Simple enough. Unfortunately the text file is populated with XML. The XML is not legitimate XML either. Here is a sample of the contents:

    thread='3288' tickCount='758272968' >
    < ![CDATA[Windows() – yes]]>

    Each entry seems to begin with an tag.

    So, I'm looking for some examples on how to format this thing? The format does not really matter as long as it looks more readable.

    by Nobody at 2013-04-10 13:11:48

    I think the best solution here is going to be getting the data YOU want. Once you have that, you can easily format however you want. So, what data are you after?

    by mjolinor at 2013-04-10 13:33:36

    Can you try this on your file and let me know the results?

    $InputFile = 'C:\DevOops\XMLish.txt'

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    $regex.matches([IO.File]::ReadAllText($InputFile)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $EventList += "Data='$($_.groups[2].value)'"
    New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    }

    by Lery at 2013-04-18 14:24:34

    [quote="mjolinor"]Can you try this on your file and let me know the results?

    $InputFile = 'C:\DevOops\XMLish.txt'

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    $regex.matches([IO.File]::ReadAllText($InputFile)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $EventList += "Data='$($_.groups[2].value)'"
    New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    }
    [/quote]

    mjolinor,

    I'm not up to regex expressions yet. Therefore, I thought this was working but seems like it's having some problems converting some of the strings. Here is the output. Is there anything you can do modify to make this work? The text file being read could have any kind of errors in it so it's hard to predict what we might have a problem converting. As a follow-up to this, when the results are returned I would love to have the latest date on top. I will be outputting this to out-gridview eventually, so I can always sort it there if need be.

    While this works, here are the errors thrown:
    ConvertFrom-StringData : Data line ']]'' is not in 'name=value' format.
    At line:17 char:42
    + New-Object psobject -Property (ConvertFrom-StringData ($EventList -joi ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [ConvertFrom-StringData], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand

    ConvertFrom-StringData : Data line ']]'' is not in 'name=value' format.
    At line:17 char:42
    + New-Object psobject -Property (ConvertFrom-StringData ($EventList -joi ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [ConvertFrom-StringData], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand

    ConvertFrom-StringData : parsing "'![CDATA[Starting SWD task: 'Windows System Assessment Scan' command line='"C:\Program Files\Altiris\Altiris Agent\Agents\SoftwareManagement\Software
    Delivery\{6D417916-467C-46A7-A870-6D86D9345B61}\cache\AexPatchAssessment.exe" -diff']]'" - Unrecognized escape sequence \P.
    At line:17 char:42
    + New-Object psobject -Property (ConvertFrom-StringData ($EventList -joi ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [ConvertFrom-StringData], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand

    ConvertFrom-StringData : parsing "'![CDATA[Launching '"C:\Program Files\Altiris\Altiris Agent\Agents\SoftwareManagement\Software
    Delivery\{6D417916-467C-46A7-A870-6D86D9345B61}\cache\STPatchAssessmentSrv.exe" /RegServer'...]]'" - Unrecognized escape sequence \P.
    At line:17 char:42
    + New-Object psobject -Property (ConvertFrom-StringData ($EventList -joi ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [ConvertFrom-StringData], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand

    by mjolinor at 2013-04-18 14:33:18

    The first rule of regex is "know your data". That one was written for and tested against data created from the sample data that was posted (that sample is all I know).

    It appears there is actually data in the file that does not match the pattern of the posted data.

    I'll need more information about that data before I'll be able to make changes to the regex to handle it.

    by Nobody at 2013-04-18 15:05:45

    So do you actually need the all the data on each line, or just specific values?

    by Lery at 2013-04-18 17:48:37

    [quote="mjolinor"]The first rule of regex is "know your data". That one was written for and tested against data created from the sample data that was posted (that sample is all I know).

    It appears there is actually data in the file that does not match the pattern of the posted data.

    I'll need more information about that data before I'll be able to make changes to the regex to handle it.[/quote]

    I understand, but I can never know what will be in the file. I can only supply samples. I really want to strangle this vendor! They're populating a text file with XML which is not really formatted properly. Any other way to accomplish this? Even if I supplied the log file it could change a minute later.

    And yes I need all the data.

    by mjolinor at 2013-04-18 18:23:37

    Can you try this and let me know if you're still getting the errors?

    $InputFile = 'C:\DevOops\XMLish.txt'

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    $regex.matches([IO.File]::ReadAllText($InputFile)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $obj = New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    $obj | Add-Member -MemberType NoteProperty -Name Data -Value ($_.groups[2].value) -PassThru
    }

    by Lery at 2013-04-19 06:15:35

    [quote="mjolinor"]Can you try this and let me know if you're still getting the errors?

    $InputFile = 'C:\DevOops\XMLish.txt'

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    $regex.matches([IO.File]::ReadAllText($InputFile)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $obj = New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    $obj | Add-Member -MemberType NoteProperty -Name Data -Value ($_.groups[2].value) -PassThru
    }
    [/quote]

    I no longer get any error messages when it runs, so I'm going to guess that is a step in the right direction 🙂 Very impressive mjolinor, thank you very much. When I try to pipe the results to out-gridview i'm not getting the entire contents of the log file. When I just run what you gave me, I do get all the results.

    by mjolinor at 2013-04-19 06:33:14

    [quote] When I try to pipe the results to out-gridview i'm not getting the entire contents of the log file. When I just run what you gave me, I do get all the results.[/quote]

    Those file paths in the some of the Data fields were messing with that convertfrom-stringdata command. It does not like backslashes. I changed to using an explicit add-member to pick up that property, and let convertfrom-stringdata take care of the rest.

    When you say you're not getting all the results, are you missing information in the rows, or are you missing entire rows?

    by Lery at 2013-04-19 07:17:54

    I stand corrected. I analyzed it again and it looks OK. For your review, if you want to look at the log, I've attached it. [attachment=1]Agent.log[/attachment] I think I'm good now. Until the data changes of course 🙂 A few beers coming your way Mjolinor.

    by mjolinor at 2013-04-19 07:31:43

    Cool.

    Not bad for a dozen lines of code 🙂

    by Lery at 2013-04-19 09:02:59

    Mjolinor,

    Will this work with many files or just one?

    For example:
    $InputFile = 'C:\DevOops\XMLish*.txt'

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    $regex.matches([IO.File]::ReadAllText($InputFile)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $obj = New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    $obj | Add-Member -MemberType NoteProperty -Name Data -Value ($_.groups[2].value) -PassThru
    }

    Throws an error saying: Exception calling "ReadAllText" with "1" argument(s): "Illegal characters in path."

    If I change it back to C:\DevOops\XMLish.txt it works just fine.

    by mjolinor at 2013-04-19 09:33:11

    It only works on one file at a time, but you can do a wildcard gci, and foreach it through that list.

    by Lery at 2013-04-19 10:23:17

    [quote="mjolinor"]It only works on one file at a time, but you can do a wildcard gci, and foreach it through that list.[/quote]

    What would the code look like?

    by mjolinor at 2013-04-19 10:44:17

    Do you want a separate object collection for each file, or one object collection with the data from all the files?

    by Lery at 2013-04-19 12:48:50

    [quote="mjolinor"]Do you want a separate object collection for each file, or one object collection with the data from all the files?[/quote]

    Ultimately I would like to have an option to either load just one of the files or all of the files. If that makes sense?

    by mjolinor at 2013-04-19 13:19:49

    Are you running V3?

    If you are, try this:

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    Get-ChildItem 'C:\DevOops\XMLish*.txt' |
    Select Name,LastWriteTime,Length,FullName |
    Out-GridView -OutputMode Multi |
    select -ExpandProperty FullName |
    foreach {
    $regex.matches([IO.File]::ReadAllText($_)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $obj = New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    $obj | Add-Member -MemberType NoteProperty -Name Data -Value ($_.groups[2].value) -PassThru
    }
    }

    Choose however many files you want to process off the gridview, and hit the OK button.

    by Lery at 2013-04-19 17:40:26

    [quote="mjolinor"]Are you running V3?

    If you are, try this:

    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@

    Get-ChildItem 'C:\DevOops\XMLish*.txt' |
    Select Name,LastWriteTime,Length,FullName |
    Out-GridView -OutputMode Multi |
    select -ExpandProperty FullName |
    foreach {
    $regex.matches([IO.File]::ReadAllText($_)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $obj = New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    $obj | Add-Member -MemberType NoteProperty -Name Data -Value ($_.groups[2].value) -PassThru
    }
    }

    Choose however many files you want to process off the gridview, and hit the OK button.[/quote]

    I'm using v3, yes. I'm running this on a Windows 2008 R2. It had v2, but I upgraded to v3. This would run on v2 and v3 environments. Possibly v1 (Windows XP) but I'm not very concerned about that version. I'll need to test this on v2 environments, yes?

    On v3 this works perfectly! As a newbie with PowerShell I'm really impressed/amazed. Thank you! I added | out-gridview so I can see the contents of whatever files I select.

    Just brilliant!

    by mjolinor at 2013-04-19 17:48:32

    That won't work on V2. Out-Gridview doesn't have that -OutputMode option.

    by Lery at 2013-04-20 13:28:46

    I see that. I ran it on a v2 machine and it certainly does not like -OutputMode. I'll specify this can only be run on a v3 machine remote or local.

    by mjolinor at 2013-04-20 14:04:58

    You can try this as a possible replacement in situations where you don't have V3:

    http://gallery.technet.microsoft.com/scriptcenter/Select-Item-V-10-beta-5e579fa6

    by Lery at 2013-04-22 08:45:29

    [quote="mjolinor"]You can try this as a possible replacement in situations where you don't have V3:

    http://gallery.technet.microsoft.com/scriptcenter/Select-Item-V-10-beta-5e579fa6[/quote]

    That works brilliantly! I'm going to add in a way to first retrieve the version of PowerShell. If v2 or lower I'll run this. If v3 I'll run the out-gridview.

    Is there anything in v2 that will display the results in an out-gridview style? Because ultimately, I need to add in prompting for a computername or IP address to run this against. In v2 I can output it in the PowerShell window, which is fine. Out-gridview just displays it really nice. Or I could output to a CSV file, HTMl page, etc. but I'd like out-gridview.

    by mjolinor at 2013-04-22 08:49:49

    You can display results with Out-Gridview in V2, you just can't select from grid (no -OutputMode).

    by Lery at 2013-04-22 09:21:14

    [quote="mjolinor"]You can display results with Out-Gridview in V2, you just can't select from grid (no -OutputMode).[/quote]

    I realized that after I replied. I was testing on Windows Server 2008 R2. Out-gridview requires the ISE to be installed. By default this seems to be installed on Windows 7. So everything works great. I added some more items and some checks for powershell versions. Now all I need to do is get this working against computers remotely.

    Thanks again Mjolinor!

    by Lery at 2013-04-22 09:33:05

    Looks like Out-GridView cannot interpret the output from a remote session as per the help on it. That is a bummer. So for remote options I'll need to figure out some other kind of output.

    by Lery at 2013-04-22 14:52:21

    I've been looking at this all day, trying to figure out if I could run this remotely or not. I'm coming to the conclusion that I cannot, but would love your input Mjolinor, or anyone else of course. I can get things to work if I just return one file. For example log.txt.

    In the situation when I have to first prompt using outgridview -OutputMode Multiple I'm out of luck. I think I'm understanding why I'm out of luck. What is the pipeline is nothing more than the results from the remote computer.

    Looks like this:


    Directory: C:\ProgramData\Vendor\Logs

    Mode LastWriteTime Length Name PSComputerName
    ---- ------------- ------ ---- --------------
    -a--- 4/22/2013 5:40 PM 25203 log.log win7
    -a--- 4/20/2013 5:30 AM 102587 log.log win7
    -a--- 4/16/2013 5:54 PM 102487 log10.log win7
    -a--- 4/17/2013 12:59 AM 102558 log11.log win7
    -a--- 4/17/2013 10:55 AM 102565 log12.log win7
    -a--- 4/17/2013 7:19 PM 102608 log13.log win7
    -a--- 4/18/2013 1:05 AM 102452 log14.log win7

    So I thought I would just need to enter back into the remote computer and run a foreach. Unfortunately, that is not working either. I was trying something like this:


    $computername = 'win7'
    Invoke-Command -ComputerName $computername -ScriptBlock {
    $getlog = get-itemproperty -path "HKLM:\SOFTWARE\abc\Event Logging\LogFile" -Name FilePath
    Get-ChildItem -Path "$($getlog.FilePath)\log*.log"} |
    Out-GridView -OutputMode Multiple | ForEach-Object {Invoke-Command $computername -ScriptBlock {Get-Content -Path $_.Fullname}}

    Again, the out-gridview works fine. Obviously when I pass the results it looks locally for the .log file and cannot find it. I also do not think that the foreach-object allows for the invoke-command. Or it allows it, but does not like me passing a -scriptblock to it.

    by mjolinor at 2013-04-22 15:01:59

    One of the reasons I wrote select-item is that Out-GridView doesn't work in a remote session.

    If you really want to use Out-GridView, you'll have to do it in the local session. It looks like the only reason you really have to have that remote session is to retrieve the path from the registry key. Once you have that, you should be able to convert that path to UNC, then do everything else in the local session where you can use Out-GridView to display the results....

    by Lery at 2013-04-22 16:38:10

    I have plans to use select-item on v2. When I tried it earlier today it worked perfectly. I'm under the impression that select-item would handle my multiple entries? Will it handle the output as well? If so I'll need to take another look at it again. My next hurdle is formatting the output.

    I think I understand the unc piece. I'll give it a shot when I'm back at my PC later.

    by Lery at 2013-04-22 18:07:01

    Before turning in for the night I went through your select-item a little further. I get everything worked just great locally. I try adding in the remote computer and I mostly end up with the error message "You cannot call a method on a null-valued expression". So I'm assuming I'm getting into the remote computer, running the select-item, returning those results and making a choice, then it gets dropped. Here is the code I'm running with select-item


    [regex]$regex = @'
    (?ms)
    \s*< (.+?)>

    '@
    Invoke-Command -ComputerName 'smpwin7single' -ScriptBlock {
    < #
    .Synopsis
    Allows user selection of objects to continue down the pipeline.
    .DESCRIPTION
    Implements a manual filter of pipeline objects by presenting the user with
    a table of the input objects, by selected properties.
    One or more objects can be selected.

    The function will return the orignal objects the display objects were derived from,
    not the display objects, so all the original properties and methods will be intact
    on the returned objects.
    The objects will be returned in the order they were selected.

    .Parameter By

    Use the -By parameter to specify the properies of the input objects you wish
    to use for the selection display. Any properties specified that do not exist
    on the first object will be discarded and a warning issued.

    You can also create custom headings and value formatting for the selection display
    using the same Label/Expression hash tables used in Select-Object for property names
    in the -By parameters.

    If the -By parameter is omitted, or no valid parameters are listed in the parameter
    arguments, a default property list will be used.

    The default property list will be the first 5 default display properties of the object type.

    .Parameter Multi

    The default is to allow selection of only one object

    Use the -Multi switch to enable selection of multiple objects.

    .Parameter Prompt

    Specifies a text string to use for the selection prompt. Default selection help text will be appended
    to the string in the console prompt.

    .Parameter Color

    Use the -Color switch to display a colorized table.
    If the switch is omitted, Format-Table will be used to display the selection table.

    .Parameter Verify

    This -Verify parameter will re-display the selected display objects and prompt the user to
    accept the selection to continue. If the user elects not to accept the selection, the
    selection table will be re-displayed and the user propted to re-enter their selection.

    .EXAMPLE
    Get-Childitem -Recurse -Include *.log |
    Sort LastWriteTime |
    Select-Item -By Name,Length,Lastwritetime -Multi -Verify -Color -Prompt 'Select log files to delete'|
    Select -ExpandProperty FullName |
    Remove-Item -Verbose

    .INPUTS
    Array of objects from the pipeline to select from.
    .OUTPUTS
    User-selected objects from the array of input objects.
    .NOTES
    Author: Rob Campbell (@mjolinor)
    Version: 1.2
    Last updated: 01/20/2013
    #>

    function Select-Item
    {

    Param
    (
    # Input objects to select from
    [Parameter(Mandatory=$true,
    ValueFromPipeline=$true)]
    [object[]]
    $InputObject,

    # Property list to use for selection display
    [Object[]]
    $By,

    # Prompt to display
    [String]
    $Prompt,

    # Select Multiple Objects
    [Switch]
    $Multi,

    # Use colorized display
    [Switch]
    $Color,

    # Re-display selected objects and prompt to verify selection or retry
    [Switch]
    $Verify
    )

    Begin
    {
    #Array for pipeline input
    [array]$_InputArray = $null

    #Script Blocks and functions

    #Function to get default display properties to use if not specied in -By

    function _Get-DefaultDisplayProperties ($_InputObject)
    {

    #Use Format-List to get default property list

    $_FormatListString =
    $_InputObject |
    format-list |
    out-string

    #Parse property list from Format-List string

    $_FormatListRegex = [regex]'(?ms)^\S+\s+:\s.+?$'

    [regex]::Matches($_FormatListString,$_FormatListRegex) |
    select -ExpandProperty Value |
    foreach {
    ($_ -split '\s:\s')[0].trim()
    }
    }
    #End function Get-DefaultPropertyList

    #Set Display format

    if (
    $color
    )
    {
    function _Show-Table ($_TableObjects) {

    $_Colors =
    @{
    0 = 'Green'
    1 = 'White'
    }

    $_DisplayText =
    $_TableObjects |
    format-table -auto |
    Out-String

    $_TextLines = $_DisplayText -split "`n"
    Write-Host ''
    Write-Host $_TextLines[1] -BackgroundColor darkcyan -ForegroundColor white

    for ($i=3 ; $i -lt $_TextLines.count ; $i++)
    {
    Write-Host $_TextLines[$i] -BackgroundColor $_colors[$i % 2] -ForegroundColor Black
    }
    }
    }

    else {
    function _Show-Table ($_TableObjects)
    {
    $_TableObjects |
    format-table -auto |
    Out-String |
    Out-Host
    }
    }
    #End Set display format

    #Function to get selected object list from user

    function _GetSelection
    {
    [string]$_Selection = $Null

    _Show-Table $_DisplayObjects

    $_Selection = Read-Host $_SelectionPrompt

    #Check for Cancel

    if ($_Selection -ieq 'C')
    {
    Write-Host 'Selection Cancelled'
    Return
    }

    #Check for All

    if (
    ($Multi) -and
    ($_Selection -ieq 'A')
    )
    {
    $_InputArray
    Return
    }

    #Check for Single item

    If (
    (-not $Multi) -and
    ($_Selection.Trim() -notmatch '^\d+')
    )
    {
    Write-host "`nInvalid selection. Enter the Item number you wish to select" -ForegroundColor Yellow
    Write-Host 'You may only select a single Item' -ForegroundColor Yellow
    . _GetSelection
    Return
    }

    #Check for invalid characters and syntax

    if (
    ($_Selection -notmatch '[0-9,.]') -or
    ($_Selection.Split(',') -notmatch '^((?:\d+\.\.\d+)|(?:\d+))$')
    )
    {
    Write-Host 'Enter selection numbers as a range and/or comma separated list.' -ForegroundColor Yellow
    Write-Host 'Examples: 3,1,2,4 1..3,7 5,1..2,4' -ForegroundColor Gray
    . _GetSelection
    Return
    }

    #Check for out of range values

    [int[]]$_Values = ($_Selection -split '\.\.|,' ) |
    sort

    if (
    ($_DisplayObjects.count -lt $_Values[-1]) -or
    ($_Values[0] -eq 0)
    )
    {
    Write-Host 'Selection is out of range.' -ForegroundColor Yellow
    . _GetSelection
    Return
    }

    #Valid array elements are selected

    #create index array from user selection string

    foreach ($_SelectedElement in ($_Selection.split(',')))
    {
    $_SelectedIndexes +=
    (Invoke-Expression $_SelectedElement)
    }

    $_SelectedIndexes =
    $_SelectedIndexes|
    foreach {
    $_ -1
    }

    if ($Verify)
    {
    $_GetConfirmation =
    {
    $_Continue =
    Read-Host 'Continue using selected objects (Y\N)'

    Switch ($_Continue)
    {
    'Y' {
    $_InputArray[$_SelectedIndexes]
    }

    'N' {
    Write-Host 'Selection Cancelled. Retry selection.'
    $_SelectedIndexes = $null
    . _GetSelection
    }

    Default {
    Write-Host 'Invalid selection' -ForegroundColor Yellow
    .$_GetConfirmation
    }
    }
    }

    Write-Host 'Selected Objects:'
    _Show-Table $_DisplayObjects[$_SelectedIndexes]
    .$_GetConfirmation
    }

    else {
    $_InputArray[$_SelectedIndexes]
    Return
    }
    }

    }

    Process
    {
    $_InputArray += $InputObject
    }

    End
    {
    if ($_InputArray)
    {

    [string[]]$_InputObjectProperties = $null

    [Object[]]$_DisplayProperties = $null

    [object[]]$_DisplayObjects = $null

    [String]$_SelectionPromptAppend = ' (C to Cancel)'

    [String]$_multiSelectionPromptAppend = ' (A for all, C to Cancel)'

    [String]$_DefaultSinglePrompt = 'Select one'

    [String]$_DefaultMultiPrompt = 'Select one or more'

    [String[]]$_Selection = $null

    [int[]]$_SelectedIndexes = $null

    #Get property list from first input object
    $_InputObjectProperties =
    $_InputArray[0].psobject.properties |
    select -ExpandProperty Name

    #Validate parameter property list

    if ($By)
    {
    foreach ($_PropName in $By)

    {
    switch ($_PropName.gettype().Name)
    {
    'String' {
    if (
    $_InputObjectProperties -notcontains $_PropName
    )
    {
    Write-Warning "Invalid property name in -By: $_PropName"
    }

    else
    {
    $_DisplayProperties += $_PropName
    }
    }

    'HashTable' {
    $_DisplayProperties += $_PropName
    }

    Default {
    Write-Warning "Invalid property type in -By: $_PropName"
    }
    }
    }

    if (
    $_DisplayProperties.count -eq 0
    )
    {
    Write-Warning 'No valid propery names found in -By. Using defult property list'
    }
    }

    #Get default property list
    if (-not $_DisplayProperties)
    {
    $_DisplayProperties =
    _Get-DefaultDisplayProperties $_InputArray[0] |
    select -First 5
    }

    #Create display objects

    [int]$_DisplayItem = 1

    #Use specified or default properties
    If ($_DisplayProperties)
    {
    $_DisplayProperties =
    @('Item') + $_DisplayProperties

    $_DisplayObjects =
    $_InputArray |
    select $_DisplayProperties

    $_DisplayObjects |
    ForEach-Object {
    $_.Item = $_DisplayItem++
    }
    }

    #No display properties. Create objects using string values of input objects

    else {
    $_DisplayObjects =
    &{foreach ($_InputObject in $_InputArray)
    {
    New-Object PSObject -Property @{
    Item = $_DisplayItem++
    Value = $_InputObject.tostring()
    }
    }
    } | select Item,Value
    }

    #Set Selection Prompt

    if ($Prompt)
    {
    $_SelectionPrompt= $Prompt
    }

    else
    {
    if ($Multi)
    {
    $_SelectionPrompt = $_DefaultMultiPrompt
    }

    else {
    $_SelectionPrompt = $_DefaultSinglePrompt
    }
    }

    if ($Multi)
    {
    $_SelectionPrompt += $_MultiSelectionPromptAppend
    }

    else {
    $_SelectionPrompt += $_SelectionPromptAppend
    }

    #Get User selection
    . _GetSelection

    }

    else {
    Write-Warning 'Select-Item: No input objects to select from'
    }
    }

    }
    #Find the location of the Altiris Agent log files via registry.
    $getlog = get-itemproperty -path "HKLM:\SOFTWARE\Altiris\Altiris Agent\Event Logging\LogFile" -Name FilePath
    #Read the contents of $getlog variable and output the log.
    Get-ChildItem -Path "$($getlog.FilePath)\agent*.log"|
    sort Fullname |
    Select-Item -By Name,Length,LastWriteTime -Multi -Color -Prompt 'Select one or more log files to view'|
    foreach {
    $regex.matches([IO.File]::ReadAllText($_)) |
    foreach {
    $EventList = ($_.groups[1].value -split "(?< =')\s") | foreach {$_.trim()}
    $obj = New-Object psobject -Property (ConvertFrom-StringData ($EventList -join "`n"))
    $obj | Add-Member -MemberType NoteProperty -Name Data -Value ($_.groups[2].value) -PassThru
    }
    }
    }

    by Lery at 2013-04-24 06:56:47

    mjolinor,

    I used select-item a lot yesterday. It works perfectly when running it locally. Is there anyway to run it remotely on a machine? I tried wrapping it in the invoke-command. I got mixed results. Example:

    Running Locally Works Great


    Get-ChildItem -Path "C:\ProgramData\Symantec\Symantec Agent\Logs\agent*.log" |
    Sort-Object LastWriteTime -desc |
    Select-Item -By Name,Length,LastWriteTime -Multi -Verify -Color -Prompt 'Pick a log DB'|
    Get-Content

    Remotely Executing Does Not Work


    Invoke-Command -ComputerName win7 -ScriptBlock {
    Get-ChildItem -Path "C:\ProgramData\abc\Logs\agent*.log" |
    Sort-Object LastWriteTime -desc |
    Select-Item -By Name,Length,LastWriteTime -Multi -Verify -Color -Prompt 'Pick a log DB'|
    Get-Content}

    The above code gets all the way to Get-Content and fails with: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that
    take pipeline input.

    Remotely Executing Works


    Invoke-Command -ComputerName win7 -ScriptBlock {
    Get-ChildItem -Path "C:\ProgramData\abc\Logs\agent*.log" |
    Sort-Object LastWriteTime -desc |
    Select-Item -By Name,Length,LastWriteTime -Multi -Verify -Color -Prompt 'Pick a log DB'}

    The above works, but returns just the equivalent of select-object. I'm looking for more of a get-content. I need to read, or better yet output to the host, the log files selected.

You must be logged in to reply to this topic.