function Start-FileTail {
param($path)
# Get unique source ID
$sourceID = "FileTailLine-" + [guid]::NewGuid()
$job = Start-Job -ArgumentList $path, $sourceID {
param($path,$sid)
Register-EngineEvent -SourceIdentifier $sid -Forward
do{}until(Test-Path $path)
$fs = New-Object IO.FileStream ($path, [IO.FileMode]::Open,
[IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)
$sr = New-Object IO.StreamReader ($fs)
$lines = @()
while(1) {
$line = $sr.ReadLine()
$lines += $line
# Send after every 100 reads
if($lines.Count -gt 100) {
# Join lines into 1 string
$text = @($lines| where {$_} ) -join "`n"
# Only send if text was found
if($text){New-Event -SourceIdentifier $sid -MessageData $text}
$lines = @()
}
}
}
$event = Register-EngineEvent -SourceIdentifier $sourceID -Action {
Write-Host $event.MessageData
}
New-Object Object|
Add-Member -Name Job -Type NoteProperty -Value $job -PassThru|
Add-Member -Name SourceIdentifier -Type NoteProperty -Value $sourceID -PassThru
}
function Stop-FileTail {
param($TailInfo)
Remove-Job $TailInfo.Job -Force
Unregister-Event -SourceIdentifier $tail.SourceIdentifier
}
Вы можете удалить задание и отменить регистрацию события после завершения установки.
Изменить Write-Host
на Write-Verbose
для -Verbose
поддержка
РЕДАКТИРОВАТЬ: Я проверил мой ответ при установке приложения и обнаружил, что это было довольно медленно при чтении файла журнала. Я обновил вызов Get-Content
, чтобы использовать -ReadCount 100
для отправки данных в виде массивов строк. Строка Write-Host
была обновлена для обработки массивов.
Я также обнаружил, что при использовании переключателя -Wait
на Start-Process
все записи журнала были записаны после завершения установки. Это можно исправить с помощью:
$msi = Start-Process -FilePath "msiexec" -ArgumentList $p -PassThru
do{}until($msi.HasExited)
РЕДАКТИРОВАТЬ 2: Хм, я не получаю весь файл журнала, когда использую -Wait
и -ReadCount
вместе. Я вернул чтение файла журнала обратно в исходное состояние. Я еще не уверен, что делать со скоростью.
РЕДАКТИРОВАТЬ 3: Я обновил код, чтобы использовать StreamReader вместо Get-Content
, и вставил код в функции. Затем вы бы назвали это как:
$path = "$ENV:TEMP\$name.log"
if(Test-Path $path){Remove-Item $path}
$msi = Start-Process -FilePath "msiexec" -ArgumentList $p -PassThru
$tail = Start-FileTail $p
do{}until($msi.HasExited)
sleep 1 # Allow time to finish reading log.
Stop-FileTail $tail