.net方法中使用的文件,但Powershell cmdlet中不使用的文件 [英] File in use with .net method but not with powershell cmdlet

查看:58
本文介绍了.net方法中使用的文件,但Powershell cmdlet中不使用的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在Powershell中打开和读取文件,请使用以下两种方法之一:

To open and read files in powershell I use one of two methods:

Get-Content $path

[System.IO.File]::OpenRead($path)

读取另一个进程正在使用的日志文件时,Get-Content似乎没有任何问题.然后,与.NET方法相比,PowerShell cmdlet仍然很慢并且使用更多的内存.但是,当我尝试使用.NET方法时,出现以下错误:

While reading a log file that is in use by another process Get-Content doesn't seem to have any issues with it. Then again the powershell cmdlet is slow and uses more memory compared to .NET method. When I try to use .NET method however, I get the following error:

该进程无法访问文件'XYZ',因为该文件正在被另一个过程."

"The process cannot access the file 'XYZ' because it is being used by another process."

Q1:为什么Powershell cmdlet可以使用.net方法访问文件?

Q1: Why can't .net method access the file whilst powershell cmdlet can?

Q2:如何使用.net方法读取文件?由于获取内容对于大约80 MB的日志文件来说太慢了.我通常只读最后一行:

Q2: And how could I read the file with .net method? Since Get-Content is too slow for log files around 80 MB. I usually read just the last line with:

$line = ""
$lineBreak = Get-Date -UFormat "%d.%m.%Y "
$bufferSize = 30
$buffer = New-Object Byte[] $bufferSize
$fs = [System.IO.File]::OpenRead($logCopy)
while (([regex]::Matches($line, $lineBreak)).Count -lt $n) {
    $fs.Seek(-($line.Length + $bufferSize), [System.IO.SeekOrigin]::End) | Out-Null
    $fs.Read($buffer, 0, $bufferSize) | Out-Null
    $line = [System.Text.Encoding]::UTF8.GetString($buffer) + $line
}
$fs.Close()

    ($line -split $lineBreak) | Select -Last $n
}

StackOverflow上原始代码的作者

任何帮助,我们将不胜感激!

PS!我正在使用Powershell 2.0,无法杀死正在使用该文件的进程.另外,我没有对该文件的写权限,只能进行读取.

PS! I'm using powershell 2.0 and can't kill the process that is using the file. Also I do not have write access to the file, just read.

推荐答案

PetSerAl 提供有效解决方案并包含解释的注释:

PetSerAl, as usual, has provided a terse comment that provides an effective solution and implies an explanation:

为防止该进程无法访问文件'XYZ',因为它正在被另一个进程使用." 错误,您必须使用共享模式 FileShare.ReadWrite ,想要拒绝写入到文件的进程.

To prevent the "The process cannot access the file 'XYZ' because it is being used by another process." error, you must open the file with sharing mode FileShare.ReadWrite, so that other processes that want to write to the file aren't denied access.

这是 Get-Content (总是)在后台执行的操作,这说明了为什么在使用 it 时问题不会浮出水面.

This is what Get-Content (invariably) does behind the scenes, which explains why the problem doesn't surface when you use it.

相反, [System.IO.File] :: OpenRead() 默认为共享模式 FileShare.Read ,这意味着其他进程可以读取,但是不能写入同一文件.

By contrast, [System.IO.File]::OpenRead() defaults to sharing mode FileShare.Read, meaning that other processes can read from, but not write to the same file.

因此,请使用 [System.IO.File] :: Open() 代替,它允许您明确指定共享模式:

Therefore, use [System.IO.File]::Open() instead, which allows you to specify the sharing mode explicitly:

$fs = [IO.File]::Open($path, 
                  [IO.FileMode]::Open, 
                  [IO.FileAccess]::Read, 
                  [IO.FileShare]::ReadWrite)
# ...
$fs.Close()

请注意,我从上面的类型名称中省略了 System.组件.该组件在PowerShell中始终是可选的.

Note that I've omitted the System. component from the type names above; this component is always optional in PowerShell.

这篇关于.net方法中使用的文件,但Powershell cmdlet中不使用的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆