none
Find locked file in a given directory RRS feed

  • Question

  • Hi,
    I have a function that detect if a file is locked before processing anything. But, How can I search for ANY locked files in a given directory? This means i don't want to mention any filename, instead i will send a directory to check if there is any locked files inside and get locked file names. Any help will be really appreciated.

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

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

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

      try
      {
     $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
     if ($oStream)
     {
       $oStream.Close()
     }
     $false
      }
      catch
      {
    # file is locked by a process.
    $true
      }
    }

    Test-FileLock -path "C:\TEL\myfile.txt"

             
    Monday, September 24, 2012 5:05 PM

Answers

  • function Test-FileLock {
       param (
     [parameter(Mandatory=$true, ValueFromPipeline=$true)]
     [string[]]$Paths
     )
     process {
     foreach ($path in $paths) {
      $oFile = New-Object System.IO.FileInfo $Path
     
      if ((Test-Path -Path $Path) -eq $false)
       {
     $false
     return
       }
     
      try
       {
      $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
      if ($oStream)
      {
        $oStream.Close()
      }
      $false
       }
       catch
       {
     # file is locked by a process.
     $true
       }
     }
     }
     }
    (gci C:\Scripts | select -ExpandProperty fullname) | Test-FileLock 


    Grant Ward, a.k.a. Bigteddy

    Monday, September 24, 2012 5:36 PM
  • Something like this?

    Function Test-Lock{ param( [parameter(ValueFromPipeline=$true)] $Path ) Process { if($Path.Attributes -ne 'Directory'){ $oFile = New-Object System.IO.FileInfo $Path.FullName $locked=$false try{ $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None) $oStream.Close() } catch{ #write-host $Error[0] $locked=$true New-Object PSObject -Property @{'Path'=$Path.FullName;'Locked?'=$locked} | Select Path,Locked? } } } } $lockedfiles=(gci c:\temp | Test-Lock)

    $lockedfiles | Format-Table -auto


    Admiral Akbar says...

    • Marked as answer by ThePathFinder Tuesday, September 25, 2012 9:35 AM
    Tuesday, September 25, 2012 12:35 AM

All replies

  • Set your parameter $path up as a string array:

    [string[]]$path

    Put the code for your function in a Process block

    Optional:

    Add this to the parameter section:

    ValueFromPipeline=$True


    Grant Ward, a.k.a. Bigteddy




    • Edited by Bigteddy Monday, September 24, 2012 5:12 PM
    Monday, September 24, 2012 5:09 PM
  • function Test-FileLock {
       param (
     [parameter(Mandatory=$true, ValueFromPipeline=$true)]
     [string[]]$Paths
     )
     process {
     foreach ($path in $paths) {
      $oFile = New-Object System.IO.FileInfo $Path
     
      if ((Test-Path -Path $Path) -eq $false)
       {
     $false
     return
       }
     
      try
       {
      $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
      if ($oStream)
      {
        $oStream.Close()
      }
      $false
       }
       catch
       {
     # file is locked by a process.
     $true
       }
     }
     }
     }
    (gci C:\Scripts | select -ExpandProperty fullname) | Test-FileLock 


    Grant Ward, a.k.a. Bigteddy

    Monday, September 24, 2012 5:36 PM
  • Hi, This worked. Thanks. But now i am facing another problem. Actually I wanted to get the list of all 'locked file' in given directory. But the solution I mentioned here, jumps to "catch" section immediately after finding the first locked file, since it's counting this as an exception. Is there any other way to detect locked files and store into an array?

    Many thanks for the help!

    Monday, September 24, 2012 10:56 PM
  • Something like this?

    Function Test-Lock{ param( [parameter(ValueFromPipeline=$true)] $Path ) Process { if($Path.Attributes -ne 'Directory'){ $oFile = New-Object System.IO.FileInfo $Path.FullName $locked=$false try{ $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None) $oStream.Close() } catch{ #write-host $Error[0] $locked=$true New-Object PSObject -Property @{'Path'=$Path.FullName;'Locked?'=$locked} | Select Path,Locked? } } } } $lockedfiles=(gci c:\temp | Test-Lock)

    $lockedfiles | Format-Table -auto


    Admiral Akbar says...

    • Marked as answer by ThePathFinder Tuesday, September 25, 2012 9:35 AM
    Tuesday, September 25, 2012 12:35 AM
  • @RiffyRiot: This worked perfectly! Thanks.

    Have a question though. I am going to add this function in a main script where i already have a TRY-CATCH handler. Is there any chance that having TRY-CATCH inside this function will interrupt the handler in main script?


    Tuesday, September 25, 2012 2:02 PM
  • from get-help try -full...

        Use the Try block to define a section of a script in which you want Windows
        PowerShell to monitor for errors. When an error occurs within the Try
        block, the error is first saved to the $Error automatic variable. Windows
        PowerShell then searches for a Catch block to handle the error. If the Try
        statement does not have a  matching Catch block, Windows PowerShell
        continues to search for an appropriate Catch block or Trap statement in the
        parent scopes. After a Catch block is completed or if no appropriate Catch
        block or Trap statement is found, the Finally block is run. If the error
        cannot be handled, the error is written to the error stream.

    If every try block is followed by a catch block then no problem.


    Admiral Akbar says...

    Tuesday, September 25, 2012 6:46 PM