无法使用二进制阅读器读取打开的文件

发布于 2024-12-23 20:29:28 字数 2291 浏览 1 评论 0原文

我有这个函数来读取 SQL Server 错误日志,但问题是我无法读取服务器当时使用的错误日志。我一直在谷歌搜索,似乎 Fileshare 标志不适用于 powershell。当我尝试打开文件时,有什么方法可以设置文件共享标志吗?

    function check_logs{
        param($logs)
        $pos
        foreach($log in $logpos){
            if($log.host -eq $logs.host){
                $currentLog = $log
                break
            }
        }
        if($currentLog -eq $null){
            $currentLog = @{}
            $logpos.Add($currentLog)
            $currentLog.host = $logs.host
            $currentLog.event = $logs.type
            $currentLog.lastpos = 0
        }
        $path = $logs.file
        if($currentLog.lastpos -ne $null){$pos = $currentLog.lastpos}
        else{$pos = 0}
        if($logs.enc -eq $null){$br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open))}
        else{
            $encoding = $logs.enc.toUpper().Replace('-','')
            if($encoding -eq 'UTF16'){$encoding = 'Unicode'}
            $br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open), [System.Text.Encoding]::$encoding)
        }
        $required = $br.BaseStream.Length - $pos
        if($required -lt 0){
            $pos = 0
            $required = $br.BaseStream.Length
        }
        if($required -eq 0){$br.close(); return $null}
        $br.BaseStream.Seek($pos, [System.IO.SeekOrigin]::Begin)|Out-Null
        $bytes = $br.ReadBytes($required)
        $result = [System.Text.Encoding]::Unicode.GetString($bytes)
        $split = $result.Split("`n")
        foreach($s in $split)
         {
            if($s.contains("  Error:"))
            {
                $errorLine = [regex]::Split($s, "\s\s+")
                $err = [regex]::Split($errorLine[1], "\s+")
                if(log_filter $currentLog.event $err[1..$err.length]){$Script:events = $events+ [string]$s + "`n" }         
            }
        }
        $currentLog.lastpos = $br.BaseStream.Position 
        $br.close()
     }

需要明确的是,当我尝试打开文件时会出现错误。错误消息是:

 Exception calling "Open" with "2" argument(s): "The process cannot access the file
 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Log\ERRORLOG' 
  because it is being used by another process."

Gísli

I have this function to read the SQL Server errorlog but the problem is that I'm not able to read the errorlog that the server is using at the time. I have been google-ing and it seems that the Fileshare flag isn't working for powershell. Is there some way to set the the Fileshare flag when I try to open the file?

    function check_logs{
        param($logs)
        $pos
        foreach($log in $logpos){
            if($log.host -eq $logs.host){
                $currentLog = $log
                break
            }
        }
        if($currentLog -eq $null){
            $currentLog = @{}
            $logpos.Add($currentLog)
            $currentLog.host = $logs.host
            $currentLog.event = $logs.type
            $currentLog.lastpos = 0
        }
        $path = $logs.file
        if($currentLog.lastpos -ne $null){$pos = $currentLog.lastpos}
        else{$pos = 0}
        if($logs.enc -eq $null){$br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open))}
        else{
            $encoding = $logs.enc.toUpper().Replace('-','')
            if($encoding -eq 'UTF16'){$encoding = 'Unicode'}
            $br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open), [System.Text.Encoding]::$encoding)
        }
        $required = $br.BaseStream.Length - $pos
        if($required -lt 0){
            $pos = 0
            $required = $br.BaseStream.Length
        }
        if($required -eq 0){$br.close(); return $null}
        $br.BaseStream.Seek($pos, [System.IO.SeekOrigin]::Begin)|Out-Null
        $bytes = $br.ReadBytes($required)
        $result = [System.Text.Encoding]::Unicode.GetString($bytes)
        $split = $result.Split("`n")
        foreach($s in $split)
         {
            if($s.contains("  Error:"))
            {
                $errorLine = [regex]::Split($s, "\s\s+")
                $err = [regex]::Split($errorLine[1], "\s+")
                if(log_filter $currentLog.event $err[1..$err.length]){$Script:events = $events+ [string]$s + "`n" }         
            }
        }
        $currentLog.lastpos = $br.BaseStream.Position 
        $br.close()
     }

To be clear the error comes when I try to open the file. The error message is:

 Exception calling "Open" with "2" argument(s): "The process cannot access the file
 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Log\ERRORLOG' 
  because it is being used by another process."

Gísli

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

执笏见 2024-12-30 20:29:28

所以我找到了答案,而且非常简单。

二进制读取器构造函数将流作为输入。我没有单独定义流,这就是为什么我没有注意到您在流的构造函数中设置了 FileShare 标志。

我要做的就是改变这个:

{$br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open))}

到这个:

{$br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite))}

然后它就像一个魅力。

吉斯利

So I found the answer and it was pretty simple.

The binary reader constructor takes as input a stream. I didn't define the stream seperately and that's why I didn't notice that you set the FileShare flag in the stream's constructor.

What I had to do was to change this:

{$br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open))}

To this:

{$br = New-Object System.IO.BinaryReader([System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite))}

And then it worked like a charm.

Gísli

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文