Stephen Cousins
Stephen Cousins

Reputation: 39

How to consolidate lots of Powershell Scripts into one

I have this script

Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Hide-Console
{
$consolePtr = [Console.Window]::GetConsoleWindow()
#0 hide
[Console.Window]::ShowWindow($consolePtr, 0)
}
Hide-Console

$docs = [environment]::GetFolderPath("MyDocuments")
$zwift = "$docs\Zwift"                  # Zwift data directory
$log = "$zwift\Logs\Log.txt"            # Path to Zwift log file
$output = "$zwift\Logs\GroupEvents.txt"  # File to write output to
$delay = 6000                           # Delay in ms between updates of the file

Function Write-SlowOutput {
[CmdletBinding()]
param (
    [Parameter(Mandatory=$true,
            HelpMessage="How long to pause for (ms)")]
[int32]$waitFor,
[Parameter(Mandatory=$false,
            HelpMessage="File to output to")]
[string]$outputFile,
[Parameter(ValueFromPipeline)]
[Object]$input
)
BEGIN {}
PROCESS {
    Write-Host $input
    if ($outputFile) {
        Out-File -Encoding UTF8 -FilePath $outputFile -InputObject $input
    }
    Start-Sleep -Milliseconds $waitFor
}
END {}

}

Get-Content -Tail 0 -Wait -Encoding "UTF8" $log | 
  Select-String "GroupEvents: Linedup for group (.*), subgroup" |
   % {$_.matches.groups[1].value} |
    Write-SlowOutput -outputFile $output -waitFor $delay

This script looks at the log file of my game and extracts some text based on the select-string line

Select-String "GroupEvents: Linedup for group (.*), subgroup" |

Expected output is a simple text phrase or sentence like Group Run. But it's really not important exactly what the text output is.

I have multiple instances of this script running each looking for a different line in the Log file and outputting a different line of text. All to the same output file. Basically the latest line found overwrites the previous one, which is what I require.

So, how can I rewrite this script so I don't need to run multiple instances, please? For example..

Select-String "GroupEvents: Linedup for group (.*), subgroup" |
Select-String "Workout(.*)" |
Select-String "GroupEvents: Started in group (.*), subgroup" |
Select-String "Run Device Selected: (.*)" |

I would like the script to search each of these strings and simply output the latest one found in the Log file to the output file.

I have tried just copying the last three lines of code, but this didn't work. I'm not a coder (clearly!) so just best guessing and using trial and error mostly.

Any help with this greatly appreciated.

Upvotes: 0

Views: 194

Answers (1)

philselmer
philselmer

Reputation: 751

Updated Answer: I'm solving the problem you are actually asking now, which is "how do I call Select-String with different patterns on the same input?"

Each time new log entries are found, it will pass all the new entries into the For-Each loop. We can then pass the current object ($_) as a pipeline object into the function ProcessLog. ProcessLog will test the input with Select-String for each pattern and pass the item to your Write-SlowOutput function.

$log = "test.log"
$output = "output.log"

$patterns = @("GroupEvents: Linedup for group (.*), subgroup", 
              "Workout(.*)", 
              "GroupEvents: Started in group (.*), subgroup", 
              "Run Device Selected: (.*)")

function ProcessLog {
    [CmdletBinding()] Param([Parameter(ValueFromPipeline)]$item)

    Write-Output "Running with $item"

    foreach($pattern in $patterns)
    {
        $save = (Select-String -InputObject $item -Pattern $pattern | % { $_.Matches.Groups[1].Value })

        if(-not [string]::IsNullOrWhitespace($save))
        {
            $save.Trim('(').Trim(')') | Set-Content $output
            return
        }
    }
}

Get-Content -Tail 0 -Wait -Encoding "UTF8" $log | % { $_ | ProcessLog }

I tested this successfully using Set-Content to write to the output file, so I just have to assume it will work properly with your Write-SlowOutput function.

Upvotes: 1

Related Questions