首页 > 解决方案 > 如何使用powershell检测特殊文件是否正在运行?

问题描述

Get-Process 仅在记事本或 exe 文件正在运行时给出结果,但我想知道某个文件夹中的特定文件(index.txt)是否在 powershell 中运行

标签: powershell

解决方案


笔记:

  • 此答案会告诉您定文件当前是否被某人打开。

  • 如果您还需要知道(哪个进程)打开了它,请参阅此相关问题的答案,但请注意,它们需要安装实用程序 ( handle.exe) 或预先配置具有管理权限的系统 ( openfiles)

  • 如果您想要此答案中提供的技术的便捷打包形式,您可以Get-OpenFiles从此Gist下载功能,该功能支持在给定目录 [子树] 中查找所有打开的文件。


与进程不同,文件没有运行,因此我假设您的意思是测试文件当前是否打开(可能已被另一个进程打开,用于读取和/或写入,并且尚未关闭)。

以下代码段检测文件是否someFile.txt在当前目录中。目前在其他地方开放:

$isOpen = try { 
    [IO.File]::Open("$PWD/someFile.txt", 'Open', 'Read', 'None').Close()
    $false # file NOT open elsewhere
  }
  catch { 
    # See if the exception is a sharing / locking error, which indicates that the file is open.
    if (
      $_.Exception.InnerException -is [System.IO.IOException] -and
      ($_.Exception.InnerException.HResult -band 0x21) -in 0x21, 0x20
    ) {
      $true # file IS open elsewhere
    }
    else {
      Throw # unexpected error, relay the exception
    }
  }

$isOpen # echo the result

注意$PWD/before someFile.txt,它显式地预先设置当前目录的路径,以便传递完整的文件名。这是必要的,因为 .NET 框架通常具有不同的当前目录。然而,前置$PWD/并不适用于所有情况。您可以在此处阅读有关它的更多信息并找到一个完全强大的解决方案。

代码尝试使用排他锁(的共享模式None)打开文件进行读取,如果文件当前处于打开状态,则会失败。

但是请注意,这仅在您至少有权读取文件时才有效。
如果不这样做,则无法执行测试,并且代码会中继[System.UnauthorizedAccessException]发生的情况;同样,来自其他意外情况的异常也会被转发,例如指定的文件不存在( [System.IO.FileNotFoundException])。

[System.IO.IOException]可以指示一系列错误条件(并且运算符-is也匹配派生类,例如[System.IO.FileNotFoundException]),因此为了专门检测共享/锁定错误,代码必须测试.HResult异常的属性以包含 Win32 API 错误代码ERROR_SHARING_VIOLATION (0x20)ERROR_LOCK_VIOLATION (0x21).

退后一步:如果最终目的是自己处理文件 [内容]最好不要事先执行单独的测试,因为文件可能会在执行测试和随后尝试打开它之间再次打开;相反,只需尝试自己打开文件并处理任何失败- 请参阅this (C#-based) answer


推荐阅读