Close locked file in Windows Share using Powershell and Openfiles

42,163

Is there a reason that you need to use both openfiles.exe and net file?
Below is a function that uses only net file and wraps it around a PowerShell Script.

To use it, you can copy the whole code, and paste it into a PowerShell session. As a side note, you need Administrator privilege to use net file and openfiles.

Once you paste it into your session, you will be able to use the function Close-OpenFile. The usage is very simple. You can either pipe the file paths into the function, or to specify the file paths as a parameter.

If you pasted it as is, you can actually get help by using Get-Help Close-OpenFile -Example to see examples. Below are the same examples for your convenience.

# Method 1 : Pipeline
@("file\path\1", "file\path\2") | Close-OpenFile
"file\path\1" | Close-OpenFile

# Method 2 : Parameter
Close-OpenFile @("file\path\1", "file\path\2")
Close-OpenFile "file\path\2"

Now, suppose you want to use this every time you open PowerShell. I've provided a basic way to do this (there are other ways to do it) at the end of this answer.

<#
.Synopsis
   Closes Files Opened in Network Share
.EXAMPLE
   @("file\path\1", "file\path\2") | Close-OpenFile
   Attempts to close "file\path\1" and "file\path\2" if they are open.
.EXAMPLE
   Close-OpenFile @("file\path\1", "file\path\2")
   Attempts to close "file\path\1" and "file\path\2" if they are open.
.EXAMPLE
   "file\path\1" | Close-OpenFile
   Attempts to close "file\path\1" if it is open.
.EXAMPLE
   Close-OpenFile "file\path\2"
   Attempts to close "file\path\2" if it is open.
#>
function Close-OpenFile {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [String[]]$filesToClose
    )
    Begin {
        $netFile = net file
        if($netFile.length -lt 7) { Throw "No Files are Open" }
        $netFile = $netFile[4..($netFile.length-3)]
        $netFile = $netFile | ForEach-Object {
            $column = $_ -split "\s+", 4
            New-Object -Type PSObject -Property @{
                ID = $column[0]
                FilePath = $column[1]
                UserName = $column[2]
                Locks = $column[3]
            }
        }
        $count = 0
    } Process {
        ForEach ($file in $filesToClose) {
            ForEach ($openFile in $netFile) {
                if($openFile.FilePath -eq $file) {
                    $count++
                    net file $openfile.ID /close > $null
                }
            }
        }
    } End { Write-Output "Closed $count Files" }
}

Below illustrates a basic way to have this function every time you open PowerShell.

  1. Navigate to $env:homepath\Documents\WindowsPowerShell (create it if you don't have it).
    This typically resolves to C:\Users\<username>\Documents\WindowsPowerShell.
  2. Create a file called profile.ps1 (or Microsoft.PowerShell_profile.ps1).
  3. Copy and Paste the entire Close-OpenFiles function and save it.
Share:
42,163
Renato Reyes
Author by

Renato Reyes

Updated on September 18, 2022

Comments

  • Renato Reyes
    Renato Reyes almost 2 years

    I work with a lot of folder shares, but there are a bunch of locked files which have been opened by some other process.

    I need to close those files. So far I've been using MMC - System Tools - Shared Folders - Open Files.

    It would be far more convenient if I could use PowerShell to filter the list/table retrieved by OpenFiles.exe and once I get the file ID close it with net file /close, or some other PS native means to similar effect.

    I am new to PowerShell, so I wonder if there is a way to create a PS script that receives the file's path and then used the file ID to close that file?