I have the following block in script that checks a log file and if it finds a specific line, should continue.
$keywords=Get-Content "C:\Users\user\desktop\keywords.txt"
Get-Content "C:\Users\user\desktop\some.log" -tail 1 -wait |
ForEach-object {
foreach($word in $keywords) {
if($_ -match "$word") {
Write-EventLog -LogName Application -EventID 2001 -EntryType Information -Source serviceCheck -Message "[SUCCESS] The service has been initialized"
Write-Host "[SUCCESS] The service has been initialized"
}
}
} | Select -First 1
This logs the event but never continues with the rest of the script.
If I put some other command in if($_ -match "$word") {get-date} for example or anything else, it works and continues to the next command.
How should this be made to write in event viewer and continue?
You need to output something for the Select -First 1 statement to react to:
$keywords = Get-Content "C:\Users\user\desktop\keywords.txt"
Get-Content "C:\Users\user\desktop\some.log" -tail 1 -wait |ForEach-object {
foreach ($word in $keywords) {
if ($_ -match "$word") {
Write-EventLog -LogName Application -EventID 2001 -EntryType Information -Source serviceCheck -Message "[SUCCESS] The service has been initialized"
Write-Host "[SUCCESS] The service has been initialized"
"literally any value will do!"
}
}
} | Select -First 1 |Out-Null
Related
I have a log file that needs to keep monitored that file looking for some keywords, I created a PowerShell script and used the get-content command with the -wait flag but, get-content is just reading the first keyword, and If I remove -wait it will work fine and read all keywords, but it will exit after finished, and I want the file to keep waiting for the appended lines.
Please advise me on this.
This is my code:
$date = Get-date -Format "yyyyMMdd"
$MyError = #('error 1', 'error 2', 'error 3')
$file=$date.log"
foreach ($i in $MyError) {
Get-Content "$file" -Wait | Select-String -Pattern $i -SimpleMatch | ForEach-Object {
if ($i -like 'error 1') {
Write-EventLog -source Test -LogName Test -EventId 1001 -EntryType Error -Message " "
}
if ($i -like 'error 2') {
Write-EventLog -source Test -LogName Test -EventId 1002 -EntryType Error -Message " "
}
if ($i -like 'error 3') {
Write-EventLog -source Test -LogName Test -EventId 1003 -EntryType Error -Message " "
}
}
}
The issue with your code is that -Wait blocks the main thread, waits indefinitely until CTRL+C. Because of this, your outer foreach loops only once, so $i is always error 1. An easy fix for your problem is to loop inside the ForEach-Object, but also, using a switch -Wildcard would simplify your code:
Get-Content path\to\file.txt -Wait | ForEach-Object {
switch -Wildcard ($_) {
'*error 1*' {
# do something for error 1
}
'*error 2*' {
# do something for error 2
}
'*error 3*' {
# do something for error 3
}
}
}
Playing around with the Get-EventLog command. The first 3 commands work as expected.
Get-EventLog Application -Newest 1000 | Select Message
Get-EventLog System -Newest 1000 | Select Message
Get-EventLog Security -Newest 1000 | Select Message
But this does not work
Get-EventLog Setup -Newest 1000 | Select Message
and this does not work
Get-EventLog setup
How come? There are WSUS errors in the Setup that we'd like to capture.
Sorry this is a bit long but I'm kind of fond of try/catch statements and over-communication.
#requires -Version 2.0
function RemoteEventLog([Parameter(Mandatory=$true)]$LogName, $MaxEvents,[Parameter(Mandatory = $true)]$computers, $LogPath)
{
<#
.SYNOPSIS
Gather remote event logs by log name by computer names.
.DESCRIPTION
Specifiy a log name to narrow down the search. Provide as many computernames as needed.
.PARAMETER maxevents
-maxevents is all about how many events.
.PARAMETER computers
The array or list of comma separated computer names to run the script through.
.PARAMETER LogPath
-LogPath will let you decide the parent folder of the location to store the logs by computer name.
.EXAMPLE
RemoteEventLog -logname Application -maxevents 1000 -computers ('host1','host2','host3')
This will loop through the computers and bring back the log for each computer.
#>
$computers = $computers -split (',')
try
{
$testLogPath = Test-Path $LogPath
}
catch
{
"Error was $_"
$line0 = $_.InvocationInfo.ScriptLineNumber
"Error was in Line $line0"
}
if(!($testLogPath))
{
try
{
New-Item -Path $LogPath -ItemType Directory -ErrorAction:Stop
}
catch
{
"Error was $_"
$line1 = $_.InvocationInfo.ScriptLineNumber
"Error was in Line $line1"
}
}
foreach($computer in $computers)
{
try
{
$log = Get-WinEvent -LogName $logName -MaxEvents $maxevents -ComputerName $computer -ErrorAction:Stop
}
catch
{
"Error was $_"
$line2 = $_.InvocationInfo.ScriptLineNumber
"Error was in Line $line2"
}
try
{
New-Item -Path $LogPath -Name ("$computer.evt") -Value $log -Force
$log | Out-File -FilePath $LogPath
}
catch
{
"Error was $_"
$line3 = $_.InvocationInfo.ScriptLineNumber
('Error was in Line {0}' -f $line3)
}
}
}
RemoteEventLog -logname Application -MaxEvents 100 -computers 'localhost,computer2,computer3' -LogPath D:\Desktop\logs
Task:
Writing piped data from object to eventlog:
RecId|Date/Time|Sev|Src|EvtType|Sensor|EvtDetail
0001|01/01/1600:00:00|INF|BMC|Eventlog|SELFullness|LogCleared
0002|01/01/1600:00:01|MAJ|BMC|Eventlog|Progress|PostError
0003|01/01/1600:00:02|INF|BMC|PowerUnit|HostPower|PowerOff
0004|01/01/1600:00:03|MAJ|BMC|SystemFirmware|SELFullness|PostError
0005|01/01/1600:00:04|INF|BMC|OsBoot||C:bootcompleted
This little CSV is stored in D:\Powershell\Bmc.log is nearly a parsed output of ipmitool.exe (isel -c) on a server.
$raw = Get-Content .\Bmc.log
$sel = ConvertFrom-CSV -InputObject $raw -Delimiter "|"
$sel | Where-Object {$_.Sev -eq "INF"} | Out-GridView
This works well, I can use $sel as object, can list its members etc.
Now I want to dump all records to eventlog, but it does not work.
My Approach:
New-Eventlog -LogName HardwareEvents -Source BMC
$sel | Where-Object {$_.Sev -eq "INF"} | Write-Eventlog -LogName HardwareEvents -Source BMC -EventId 999 -Message {$_.EvtDetail} -EntryType INFORMATION
It seems that Write-Eventlog does not accept pipes.
Aim is not to use a loop.
As you suspected and others have pointed out, Write-EventLog doesn't read from the pipeline. Wrap it in a ForEach-Object statement:
$sel | Where-Object {$_.Sev -eq "INF"} | ForEach-Object {
Write-EventLog -LogName HardwareEvents -Source BMC -EventId 999 -Message $_.EvtDetail -EntryType INFORMATION
}
Otherwise you'd need to wrap Write-EventLog in a custom function that does process pipeline input:
function Write-EventLogMessage {
[CmdletBinding()]
Param(
[Parameter(
Mandatory=$true,
Position=0
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[string]$Message
)
Process {
Write-EventLog -LogName HardwareEvents -Source BMC -EventId 999 -Message $Message -EntryType INFORMATION
}
}
$sel | Where-Object {$_.Sev -eq "INF"} | Write-EventLogMessage
Hi all powershell gurus out there.
I have a foreach which opens a URL from URLListl.txt and doing a Measure-command on them. The result from Measure-command writes to event-log.
In another text file i have country list, like:
USA
Canada
Brazil
and so on....
I want in write eventlogs Message to read from this Text file and write it with the Measure-command result in Message part of the eventlog.
The below is my script which works fine but it creates two entries for each URL.
{
$URLListFile = "C:\yourname\URLList.txt"
$URLList = Get-Content $URLListFile -ErrorAction SilentlyContinue
Foreach ($Uri in $URLList)
{
$Time = Measure-Command {
C:\yourname\MainScript.ps1}
$Time.TotalSeconds
$countrycode = (Get-Content c:\yourname\URLListcountry.txt)
foreach ($SiteCode in $CountryCode)
{
$LogFileExist = Get-EventLog -list | Where-Object { $_.LogDisplayName -eq "Scriptcheck" }
if (! $LogFileExist)
{
New-EventLog -LogName "Scriptcheck" -Source "Scripts"
}
if ($Time.Totalseconds -lt 25)
{
Write-EventLog -LogName "Scriptcheck" -Source "Scripts" -EntryType information -EventId 100 -Message " $SiteCode `nTotal Time: $Time"
}
elseif ($Time.Totalseconds -gt 25)
{
Write-EventLog -LogName "Scriptcheck" -Source "Scripts" -EntryType warning -EventId 101 -Message " $SiteCode `nTotal Time: $Time"
}
}
}
}
if (Get-Process -name iexplore -ErrorAction SilentlyContinue)
{
Stop-Process -Name iexplore
}
Measure-Site
Import-Module ActiveDirectory
$Content = Get-Content C:\SMS\sms.txt -TotalCount 1
ForEach ($Payroll in ($Content )) {
Get-ADUser -Identity "$Payroll" -Properties LockedOut | Select-Object LockedOut
If ($true) {$true -ne $false}
Unlock-ADAccount $Payroll
If ($true) {$true -ne $false}
Write-EventLog -LogName "ADUnlock" -Source ADUnlock -EntryType Information -Message "AD account Successfully unlocked $Payroll" -Category 1 -EventId "12"
If ($false) {$false -ne $true}
Write-EventLog -LogName "ADUnlock" -Source ADUnlock -EntryType Information -Message "AD account Attempted to unlock but failed $Payroll" -Category 1 -EventId "12"
}
I am attempting to Write to the event log on success and error using the $true and the $false booleans but it is writing the two event logs despite the success or error, I have tried different variations of the code by using $LASTEXITCODE but then realized that it is for Win32 applications not for PowerShell Command lets.
I'm not entirely sure what you're doing with those if statements but I think you might want something like this:
Import-Module ActiveDirectory
$Content = Get-Content C:\SMS\sms.txt -TotalCount 1
ForEach ($Payroll in ($Content )) {
$res = Get-ADUser -Identity "$Payroll" -Properties LockedOut | Select-Object LockedOut
If (!res) {continue}
Unlock-ADAccount $Payroll
if ($?) {
Write-EventLog -LogName "ADUnlock" -Source ADUnlock -EntryType Information -Message "AD account Successfully unlocked $Payroll" -Category 1 -EventId 12
}
else {
Write-EventLog -LogName "ADUnlock" -Source ADUnlock -EntryType Information -Message "AD account Attempted to unlock but failed $Payroll" -Category 1 -EventId 12
}
}
Thing is, I'm not sure what the type of LockedOut is. I'm assuming a Boolean here.