我正在为我公司的桌面应用程序编写安装和配置过程的脚本。我们发出 kiosk不能把所有东西都放在安装程序中……继续前进!我正在使用 Start-Process
等待msiexec
至 complete .
function Run-Installer
{
param
(
[string] $msi = $(throw "Required parameter: 'msi'"),
)
if(-not(Test-Path $msi -Type Leaf))
{
throw "The installer could not be found: '$msi'"
}
$name = (Get-Item $msi).BaseName
Write-Host "Installing $name"
$p =
@(
"/I `"$msi`"", # Install this MSI
"/QN", # Quietly, without a UI
"/L*V `"$ENV:TEMP\$name.log`"" # Verbose output to this log
)
Start-Process -FilePath "msiexec" -ArgumentList $p -Wait
}
我想看中的是 msiexec
的日志输出。我想在安装程序运行时将日志内容流式传输到控制台。我猜解决方案有多个部分
- 在后台以可等待的方式运行安装程序
- 跟踪日志文件直到满足某些条件(安装程序作业完成)
- 可选:过滤输出或写入 debug/verbose 以获得乐趣
最佳答案
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
行已更新以处理数组。
我还发现,在 Start-Process
上使用 -Wait
开关会导致在安装完成后写入所有日志输出。这可以通过使用来解决:
$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
关于powershell - 如何跟踪由于 PowerShell 脚本中较早的命令而写入的日志文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7109366/