Powershell:检查文件是否被锁定

28

我在自动化部署时遇到一个问题,停止服务后文件仍然被锁定,导致无法删除。我不想使用等待的方式来解决这个问题,因为这不是一个可靠的方法。是否有一种良好的方式来解决锁定文件的问题,比如某种“等待文件可删除”的方法:

Get-ChildItem:拒绝访问路径“D:\MyDirectory\”。

在这种情况下,“Test-Path”是不够的,因为该文件夹已经存在,而且我也有访问权限。


3
如何在尝试复制文件之前检查文件是否已打开/锁定?我需要编写一个PowerShell脚本,该脚本将检查指定的文件是否正在被其他进程打开或锁定。如果文件未被打开/锁定,则脚本将执行文件复制操作。如何实现这一点? - David Brabant
4个回答

55

感谢David Brabant在最初的问题下发布了此解决方案的链接。似乎我可以通过以下函数开始完成此操作:

function Test-FileLock {
  param (
    [parameter(Mandatory=$true)][string]$Path
  )

  $oFile = New-Object System.IO.FileInfo $Path

  if ((Test-Path -Path $Path) -eq $false) {
    return $false
  }

  try {
    $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)

    if ($oStream) {
      $oStream.Close()
    }
    return $false
  } catch {
    # file is locked by a process.
    return $true
  }
}

然后添加一个带有超时的“等待”函数。

感谢您的帮助!


我尝试过这个方法,但似乎除非我在Test-FileLock中添加一个write-output语句,否则它不起作用。我做错了什么吗?如果(Test-FileLock -path $file){ Write-Output“跳过锁定文件$File” } 否则{ $null = Move-Item -Path $file.FullName -Destination $dir_path
}
- Ching Liu

26

我使用这个:

try { [IO.File]::OpenWrite($file).close();$true }
catch {$false}

2
一个将try/catch作为逻辑if/else的做法感觉很糟糕,但我想如果没有其他方法... - Matthew Bonig
3
$file 应为绝对路径,例如:[IO.File]::OpenWrite((Resolve-Path $file).Path).close()。否则,它将默认为主目录并成为难以调试的逻辑错误。 - mvanle
4
请注意,如果文件已被锁定,此代码将返回false,而@Dech的答案会在文件被锁定时返回true。 - 3VYZkz7t
我的直觉是:如果你打开一个文件进行写操作,那么不会清除其内容吗?来自@Dech的回答至少提供了读写的选项 - 所以如果文件存在,它不会清空内容。有人可以确认我的猜测吗?虽然我猜想如果被另一个任务锁定,可能会阻止这种情况发生。但如果没有被锁定,你不会清除数据吗?如果是这样的话,这将是一个糟糕的副作用! - JGFMK

2
$fileName = "C:\000\Doc1.docx"
$file = New-Object -TypeName System.IO.FileInfo -ArgumentList $fileName
$ErrorActionPreference = "SilentlyContinue"
[System.IO.FileStream] $fs = $file.OpenWrite(); 
if (!$?) {
    $msg = "Can't open for write!"
}
else {
    $fs.Dispose()
    $msg = "Accessible for write!"
}
$msg

1

Simplified:

Function Confirm-FileInUse {
    Param (
        [parameter(Mandatory = $true)]
        [string]$filePath
    )
    try {
        $x = [System.IO.File]::Open($filePath, 'Open', 'Read') # Open file
        $x.Close() # Opened so now I'm closing
        $x.Dispose() # Disposing object
        return $false # File not in use
    }
    catch [System.Management.Automation.MethodException] {
        return $true # Sorry, file in use
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接