【问题标题】:How to detect if a special file is running or not with powershell?如何使用powershell检测特殊文件是否正在运行?
【发布时间】:2018-08-03 00:10:40
【问题描述】:

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

【问题讨论】:

  • 如果您通过 CMD 启用 OpenFiles /local on(并重新启动),那么您可以在 CMD 中运行 OPENFILES /Query 以检索所有打开的带锁文件的列表。由于 .txt 文件不会创建锁,因此这不适用于这种文件格式,但适用于其他格式(例如办公文件)。最终目的是什么,或者您为什么需要这些信息?也许还有另一种方法可以用来满足最终需求。
  • 只是添加到上面的评论中,谁/什么会打开这个文件?这是您可以控制的吗,因为您可以在 CMD 中使用 notepad >> filetolock.txt 锁定 .txt 文件,然后通过 OPENFILES /Query 看到它
  • @BACON:当然相关,但不完全重复:链接的问题想知道 锁定了给定文件,而这个问题似乎只询问 是否被锁定。前者似乎需要安装实用程序或预先配置,而后者并非绝对必要。当然,最终结果可能是 OP 想知道
  • @mklement0 这是一个值得注意的区别。这个问题缺乏细节和清晰度:它似乎想要一个通用的解决方案,但也特别提到了记事本,根据handle.exe,它似乎没有为加载的文件保留打开的句柄。我把重复的想法联系起来“这是我认为你想问的更好的版本,或者足够接近。”再一次,当问题没有提到它们时,你、我和雅各布开始考虑引擎盖下的锁;也许它真的是在询问是否有任何应用程序有一个文件加载,我不确定是否有一个通用的解决方案。

标签: powershell


【解决方案1】:

您可以使用mainWindowTitle 方法,然后选择正在运行的进程的名称。像这样的 -

get-Process notepad | where-Object {$_.mainWindowTitle} | Select-Object id, name, mainwindowtitle

这将为您提供正在运行的记事本进程列表,如果您在 MainWindowTitle 标题下找到您的文件 index.txt,则可以确认您的文件确实在运行。

【讨论】:

  • 但是mainwindowtitle通常不包含路径,所以不能肯定满足want to know if a specific file (index.txt) which is in some folder的要求。
【解决方案2】:

Get-Process 获取所有正在运行的进程。 文本文件不是进程,当然是/在进程中打开的对象(无论PS是否启动),记事本,winword等...

PS 可用于启动进程,例如记事本,但 PS 不拥有它,exe 拥有。

因此,在您询问的上下文中,文件永远不会在 PS 中运行,可以使用 Get-Process(或 Get-Process 替换的旧任务列表工具)查找该进程(在您的系统上运行)作为以及运行进程的路径信息。

  1. 手动启动记事本并打开一个文本文件。
  2. 运行 Get-Process 并询问记事本进程的所有值。

您将看到 Get-Process 带回大量信息供您选择。 请注意,它是 MainWindowTitle,它显示了记事本进程打开了哪个文件,但在此结果中没有说明该文件(路径)是从哪里运行的。

Get-Process Notepad | Select-Object *

Name                       : notepad
Id                         : 20516
...
Path                       : C:\WINDOWS\system32\notepad.exe
Company                    : Microsoft Corporation
CPU                        : 2.515625
ProductVersion             : 10.0.17134.1
Description                : Notepad
Product                    : Microsoft® Windows® Operating System
__NounName                 : Process
...
MainWindowTitle            : news-stuff.txt - Notepad
MainModule                 : System.Diagnostics.ProcessModule (notepad.exe)
...

【讨论】:

    【解决方案3】:

    注意:

    • 此答案告诉您如果给定文件当前被某人打开。

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

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


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

    下面的 sn -p 检测文件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
    

    注意someFile.txt 之前的$PWD/,它显式地添加了当前目录的路径,以便传递完整的文件名。这是必要的,因为 .NET 框架通常有一个不同的当前目录。但是,添加 $PWD/所有情况下都不起作用;你可以阅读更多关于它并找到一个完全强大的解决方案here

    代码尝试使用排他锁(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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      相关资源
      最近更新 更多