2011-08-18 45 views
2

我正在编写我公司桌面应用程序的安装和配置程序。我们发送一个kiosk,并且不能将所有内容都放入安装程序中......一起移动!我正在使用Start-Process来等待msiexeccomplete如何由于PowerShell脚本中的早期命令而使正在编写的日志文件尾尾?

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的日志输出。我想在安装程序运行时将日志的内容传输到控制台。我猜有多个部分的解决方案

  1. 运行在后台安装,可等待的方式
  2. 拖尾日志文件,直到某些条件得到满足(安装作业完成)
  3. 可选:过滤输出或写入调试/详细乐趣

回答

4
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-HostWrite-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 
+0

哇,感谢所有的工作!今晚我可能有时间来实施这个。我会定期检查:) –

+0

仍然没有尝试过解决方案,它是为了在工作中的一个侧面项目,并且你不知道它,我的主要责任继续妨碍:)但是,你已经等待足够长的代表! –

相关问题