开发者

Seek method not working in Powershell script

I´m trying to use the .net API to seek in a large data file. For some reason I am unable to make it work. Here is my code:

function check_logs{
  $pos = 8192
  $count = 1
  $path = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Log\ERRORLOG.2'
  $br = 0
  $reader = [System.IO.File]::OpenText($path)
  $reader.DiscardBufferedData()
  $reader.BaseStream.Seek(0, [System.IO.SeekOrigin]::Begin)
    for(;;){
    $line = $reader.ReadLine()
    if($line -ne $null){$br = $br + [System.Text.Encoding]::UTF8.GetByteCount($line)}
    if($line -eq $null -and $count -eq 0){break}
    if($line -eq $null){$count = 0}
    elseif($line.Contains('  Error:')){
        Write-Host "$line  $br"
    }
}

}

If I use 0 as a parameter for the seek method it seeks from the beginning as expected but it also writes 0 out to the console before it writes the lines read. Example:

 0
 2011-08-31 09:26:36.31 Logon       Error: 17187, Severity: 16, State: 1.  4101
 2011-08-31 09:26:36.32 Logon       Error: 17187, Severity: 16, State: 1.  4489
 2011-08-31 09:26:38.25 Logon       Error: 17187, Severity: 16, State: 1.  4929
 2011-08-31 09:26:38.25 Logon       Error: 17187, Severity: 16, State: 1.  5304
 2011-08-31 09:26:43.75 Logon      开发者_如何学Python Error: 17187, Severity: 16, State: 1.  6120

If I try to seek using 4096 instead of 0 it only writes out:

4096

I would have thought it would write out the same lines as the first one did apart from the first two.

Can someone see the problem? I had another question that got me to this. For further background see this

EDIT: Still trying to figure this out. Does anyone know where else I could try to find information regarding this problem? Is it possible to send questions to the Microsoft scripting guy?

Best regards

Gísli


The Seek method returns the new position within the stream, which is why you are having a number printed out.

As to why you are not getting an output:

  1. Confirm the file is greater than 4K in size.
  2. Try printing out all lines, rather than just lines with the word "Error" in them. That might give you a clue
  3. StreamReader is a buffered wrapper around the base stream, so Seek and Position may not work quite like you expect. Consider http://geekninja.blogspot.com/2007/07/streamreader-annoying-design-decisions.html. Try adding in a call to $reader.DiscardBufferedData() before the seek.


So I finally found the answer. For some reason unknown to me I have to use a binary reader. Here below is my complete function:

 function check_logs{
 Write-Host "New test `n`n"
 $pos = 19192
 $path = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Log\ERRORLOG.2'
 $br = 0
 $b = new-object System.IO.BinaryReader([System.IO.File]::Open($path,[System.IO.FileMode]::Open));
 $required = $b.BaseStream.Length - $pos
 $b.BaseStream.Seek($pos, [System.IO.SeekOrigin]::Begin)
 $bytes = $b.ReadBytes($required)
 $log = [System.Text.Encoding]::Unicode.GetString($bytes)
 $split = $log.Split("`n")
 foreach($s in $split)
 {
     if($s.contains("  Error:"))
     {
         Write-Host $s  "`n"
     }
 }
 $b.close
 }

Thanks for the help

Gísli


I had a similar problem. The seeked-off position was getting printed on the console. I just had to assign the return value to some variable, and that solved the problem.

So instead of:

$reader.BaseStream.Seek(0, [System.IO.SeekOrigin]::Begin)

I had to write something like:

$pos = $reader.BaseStream.Seek(0, [System.IO.SeekOrigin]::Begin)

Regards, Thejasvi V

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜