-2

Get-Process only gives the result if a notepad or exe file is running but I want to know if a specific file (index.txt) which is in some folder is running or not in powershell

  • 1
    If you enable `OpenFiles /local on` via CMD (and reboot) then you can run `OPENFILES /Query` in CMD to retrieve a list of all open files with locks. As .txt files don't create locks, this wouldn't work for this file format, but would work for other formats (such as office files). What is the end purpose, or why do you need this information? Maybe there's another approach that could be used to meet the end needs. – Jacob Jul 28 '18 at 14:34
  • Just to add to the above comment, who/what would be opening this file? Is this something that would be in your control, because you can lock a .txt file by using `notepad >> filetolock.txt` in CMD and then see it via `OPENFILES /Query` – Jacob Jul 28 '18 at 14:44
  • 1
    Possible duplicate of [PowerShell script to check an application that's locking a file?](https://stackoverflow.com/questions/958123/powershell-script-to-check-an-application-thats-locking-a-file) – Lance U. Matthews Jul 28 '18 at 17:52
  • @BACON: Certainly related, but not quite a duplicate: the linked question wants to know _who_ locked a given file, whereas this question seems to ask only for _whether_ it is locked. The former seems to require installation of a utility or prior configuration, which is not strictly necessary for the latter. Of course, it may turn out that the OP wanted to know _who_ after all. – mklement0 Jul 28 '18 at 18:52
  • 1
    @mklement0 That is a noteworthy distinction. This question lacks details and clarity: it seems to want a general solution but also mentions Notepad specifically, which, according to handle.exe, does not appear to keep open handles for the loaded file. I linked the duplicate thinking "Here's a better version of what I think you're trying to ask, or close enough." Then again, you, I, and Jacob started thinking of locks under the hood when the question doesn't mention them; maybe it really is asking if any application has a file _loaded_, for which I'm not sure there can be a general solution. – Lance U. Matthews Jul 28 '18 at 19:59

3 Answers3

2

Get-Process gets all running processes. A text file is not a process, it of course is an object opened by / in a process (whether PS started it or not), notepad, winword, etc...

PS can be used to start a process, say notepad, but PS does not own it, the exe does.

So, a file, in the context you are asking, is never running in PS, the process (running on your system) can be looked up using Get-Process (or the old Tasklist tool which Get-Process replaces) as well as the path information of the running process.

  1. Start notepad manually and open a text file.
  2. Run Get-Process and ask for all values of the notepad process.

You will see the Get-Process brings back a whole lot of info for you to select from. Note that it is the MainWindowTitle, which shows what file the Notepad process has open, but no where in this results does it say where that file (path) is ran from.

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)
...
postanote
  • 15,138
  • 2
  • 14
  • 25
1

You can use the mainWindowTitle method and then select the names of the processes running. Something like this -

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

This will give you the list of notepads processes running, and if you find your file index.txt under the MainWindowTitle header then, you can confirm that your file is running indeed.

Vivek Kumar Singh
  • 3,223
  • 1
  • 14
  • 27
  • 1
    But `mainwindowtitle` usually doesn't include the path, so the requirement `want to know if a specific file (index.txt) which is in some folder` can't be met for sure. –  Jul 28 '18 at 09:51
1

Note:

  • This answer tells you if a given file is currently held open by someone.

  • If you also need to know who (what process) has it open, see the answers to this related question, but note that they require either installation of a utility (handle.exe) or prior configuration of the system with administrative privileges (openfiles)

  • If you want a conveniently packaged form of the technique presented in this answer, you can download function Get-OpenFiles from this Gist, which supports finding all open files in a given directory [subtree].


Files, unlike processes, aren't running, so I assume that you meant to test if a file is currently open (has been opened, possibly by another process, for reading and/or writing, and hasn't been closed yet).

The following snippet detects if file someFile.txt in the current dir. is currently open elsewhere:

$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

Note the $PWD/ before someFile.txt, which explicitly prepends the path to the current directory so as to pass a full filename. This is necessary, because the .NET framework typically has a different current directory. Prepending $PWD/ doesn't work in all situations, however; you can read more about it and find a fully robust solution here.

The code tries to open the file for reading with an exclusive lock (a sharing mode of None), which fails if the file is currently open.

Note, however, that this only works if you have permission to at least read the file.
If you don't, the test cannot be performed, and the code relays the [System.UnauthorizedAccessException] that occurred; similarly, exceptions from other unexpected conditions are relayed, such as the specified file not existing ([System.IO.FileNotFoundException]).

[System.IO.IOException] can indicate a range of error conditions (and operator -is also matches derived classes such as [System.IO.FileNotFoundException]), so in order to specifically detect sharing/locking errors, the code must test the .HResult property of the exception for containing Win32 API error codes ERROR_SHARING_VIOLATION (0x20) or ERROR_LOCK_VIOLATION (0x21).

Taking a step back: If the intent is ultimately to process the file [content] yourself, it's better not to perform a separate test beforehand, because the file may get opened again between performing your test and your subsequent attempt to open it; instead, simply try to open the file yourself and handle any failure - see this (C#-based) answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775