【问题标题】:How to check if file is being used by another process - Powershell如何检查文件是否被另一个进程使用 - Powershell
【发布时间】:2012-02-22 12:21:48
【问题描述】:

我正在尝试找到一个解决方案来检查文件是否正在被另一个进程使用。我不想阅读文件的内容,因为在 7GB 文件上,这可能需要一段时间。目前我正在使用下面提到的函数,这并不理想,因为脚本需要大约 5 - 10 分钟来检索一个值。

function checkFileStatus($filePath)
{
    write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked"

    if(Get-Content $filePath  | select -First 1)
    {
        write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath
        return $true
    }
    else
    {
        write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked"
        return $false
    }
}

任何帮助将不胜感激

【问题讨论】:

    标签: .net file powershell


    【解决方案1】:

    创建了一个解决上述问题的函数:

     function checkFileStatus($filePath)
        {
            write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked"
            $fileInfo = New-Object System.IO.FileInfo $filePath
    
            try 
            {
                $fileStream = $fileInfo.Open( [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read )
                write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath
                return $true
            }
            catch
            {
                write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked"
                return $false
            }
        }
    

    【讨论】:

    • 非常感谢您的代码。这是非常有用的。我正在使用它来测试共享网络位置上的文件是否可供使用。每隔几天他们就会将一个新的大文件上传到该位置(这需要几个小时才能上传),我想确保上传完成,以便我可以安全地将该文件复制并下载到我的本地计算机。你觉得我的概念有什么缺陷吗?
    • 这是否有原因在退出之前没有调用$fileStream.Dispose()
    • @user2426679 我听说垃圾收集器会处理它,除非你在某个时间范围内创建了太多对象
    • 这实际上并不像我写的那样工作,需要将$fileStream = $fileInfo.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read) 替换为$fileStream = $fileInfo.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Read) 以在文件被另一个进程使用时触发错误。
    • 这里的所有解决方案都对我返回了误报。就像文件总是被锁定
    【解决方案2】:

    我用来检查文件是否被锁定的功能:

    函数 IsFileLocked([string]$filePath){ 重命名项目 $filePath $filePath -ErrorVariable errs -ErrorAction SilentlyContinue 返回 ($errs.Count -ne 0) }

    【讨论】:

    • 就我而言,这不起作用。我想复制现有文件,所以我对其进行了检查,没有出现任何错误,但是当它进入复制步骤时,出现一个错误,表明该文件正在被另一个进程使用。
    【解决方案3】:
    function IsFileAccessible( [String] $FullFileName )
    {
      [Boolean] $IsAccessible = $false
    
      try
      {
        Rename-Item $FullFileName $FullFileName -ErrorVariable LockError -ErrorAction Stop
        $IsAccessible = $true
      }
      catch
      {
        $IsAccessible = $false
      }
      return $IsAccessible
    }
    

    【讨论】:

    • 在你的答案中添加一些 cmets。
    【解决方案4】:

    poschcode.org 上查看此脚本:

    filter Test-FileLock {
        if ($args[0]) {$filepath = gi $(Resolve-Path $args[0]) -Force} else {$filepath = gi $_.fullname -Force}
        if ($filepath.psiscontainer) {return}
        $locked = $false
        trap {
            Set-Variable -name locked -value $true -scope 1
            continue
        }
        $inputStream = New-Object system.IO.StreamReader $filepath
        if ($inputStream) {$inputStream.Close()}
        @{$filepath = $locked}
    }
    

    【讨论】:

    • 仅供参考,这不是 PoshCode 链接。
    • 谢谢,在链接的帮助下,我创建了一个新的函数来满足需要。
    • @user983965,如果您能够解决您的问题,您应该在 SO 上发布解决方案作为答案。指向解决方案的链接不太有用,因为目标页面可能会更改或消失。
    • @DourHighArch 或成为一个糟糕的网站
    【解决方案5】:

    既然您不想读取该文件,我建议您使用像 Sysinternals Handle.exe 这样的实用程序,它会为一个进程吐出所有打开的句柄。您可以从这里下载 Handle.exe:

    http://technet.microsoft.com/en-us/sysinternals/bb896655

    您可以不带任何参数运行 Handle.exe,它会返回所有打开的文件句柄。如有必要,您可以解析输出,或者仅将输出与您的完整文件路径进行匹配。

    【讨论】:

      猜你喜欢
      • 2014-07-12
      • 1970-01-01
      • 2012-03-09
      • 2013-01-09
      • 1970-01-01
      • 2012-04-24
      • 1970-01-01
      • 2010-12-29
      • 2011-09-23
      相关资源
      最近更新 更多