openfiles.ps1
<#PSScriptInfo
.VERSION 1.2 .GUID 579b9002-4c7a-4f16-b5ab-91f434aa9854 .AUTHOR Christoph Weste .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Fixed bug in terminate switch #> <# .DESCRIPTION dealing with openfiles using openfiles.exe #> Param() #!/usr/bin/env powershell #Requires -RunAsAdministrator function Get-OpenFiles { <# .SYNOPSIS This function will display open files from a given Sever / PC .DESCRIPTION This function will use openfiles.exe to get information about open files against a given Sever / PC. It will return an DataTable object with all openfiles or if the -filter property is used it will return an filter Dataview object. You can also close open files if you use the terminate switch .EXAMPLE Will return all openfiles on fileserver1 Get-OpenFiles -ComputerName fileserver1 .EXAMPLE Will return all openfiles from fs2 where the filname contains \share\ Get-OpenFiles -computername fs2 -Filter Open_File -query \share\ .EXAMPLE Will return all openfiles from all servers (which are in the clipboard) which are accessed by backupadmin get-clippboard|Get-OpenFiles -Filter Accessed_By -query backupadmin .EXAMPLE You can also skip the -filter and only working with -User_q or -File_q Get-OpenFiles -User_q backupadmin .EXAMPLE You can also skip the -filter and only working with -User_q or -File_q Get-OpenFiles -File_q \share\ .EXAMPLE It also possible to combine queries. This example will return all files which are opend by the user backupadmin with \share\ in the pathname Get-OpenFiles localhost -Filter Combo -User_q backupadmin -File_q \share\ .EXAMPLE This will close/terminate all sessions from the user backupadmin Get-OpenFiles -Filter Accessed_By -query backupadmin -terminate .PARAMETER computername The computer name to query. Just one or multiple. .PARAMETER Filter Here you can select which poperty is interesting for your result. .PARAMETER User_q This is your user search query , you dont have to provide the exact search query the function will always use LIKE .PARAMETER File_q This is your File search query , you dont have to provide the exact search query the function will always use LIKE .PARAMETER terminate This parameter will trigger an close/discconect against the openfiles which are returned #> [CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'Low')] [CmdletBinding(DefaultParameterSetName = 'set1')] Param ( [Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = 'What computer name would you like to target?')] [string[]]$computername, [Parameter(Position = 1)] [ValidateSet('Open_File','Accessed_By','Combo')] [AllowEmptyString()] [String]$Filter, [Parameter(Position = 2)] [AllowEmptyString()] [String]$User_q, [Parameter(Position = 3)] [AllowEmptyString()] [String]$File_q, [Parameter(Position = 4)] [switch]$Terminate = $false ) begin { If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match 'S-1-5-32-544')) { Write-Verbose -Message 'You are an administrator' } else { Write-Verbose -Message 'You need Admin rights to execute openfiles.exe' break } } process { Write-Verbose -Message ('Beginning query {0}' -f $computername) # openfile execution $temp = & "$env:windir\system32\openfiles.exe" /query /s $computername /fo csv /V #modify the header row , this makes filtering easier , lazy me $temp[0] = '"Hostname","ID","Accessed_By","Type","Locks","Open_Mode","Open_File"' $csv = $temp | ConvertFrom-Csv # Create Datatable $dtFileAccess = New-Object -TypeName System.Data.DataTable -ArgumentList ('FileAccess') $cols = @('Hostname', 'ID', 'Accessed_By', 'Locks', 'Open_Mode', 'Open_File') # Schema (columns) foreach ($col in $cols) { $null = $dtFileAccess.Columns.Add($col) } # Fill the Datatable with Values (rows) foreach ($c in $csv) { $row = $dtFileAccess.NewRow() foreach ($col in $cols) { $row[$col] = $c.$col } $null = $dtFileAccess.Rows.Add($row) } # This will be used for filtering # DataView rapid filter $dvFileAccess = New-Object -TypeName System.Data.DataView -ArgumentList ($dtFileAccess) switch ($Filter){ 'Accessed_By' { If ($Terminate -ne $True) { $dvFileAccess.RowFilter = 'Accessed_By'+(" LIKE '%{0}%'" -f $User_q) return $dvFileAccess } } 'Open_File' { If ($Terminate -ne $True) { $dvFileAccess.RowFilter = ("Open_File LIKE '%{0}%'" -f $File_q) return $dvFileAccess } } 'combo' { If ($Terminate -ne $True) { $dvFileAccess.RowFilter = "Accessed_By LIKE '%{0}%'AND Open_file LIKE '%{1}%'" -f $User_q, $File_q return $dvFileAccess } } default { If ($Terminate -ne $True) { If ($File_q -ne $null -or $User_q -ne $null) { $dvFileAccess.RowFilter = "Accessed_By LIKE '%{0}%'AND Open_file LIKE '%{1}%'" -f $User_q, $File_q return $dvFileAccess } else { return $dtFileAccess } } } } # Result if ( $Terminate -eq $True ) { #-and $dvFileAccess.GetEnumerator() -gt 0){ If ($File_q -ne $null -or $User_q -ne $null) { $dvFileAccess.RowFilter = "Accessed_By LIKE '%{0}%'AND Open_file LIKE '%{1}%'" -f $User_q, $File_q } $result = [System.Collections.ArrayList]@() foreach ($id in $dvFileAccess.GetEnumerator().id) { $r = & "$env:windir\system32\openfiles.exe" /disconnect /s $computername /id $id if ($r -ne $null) { $null = $result.Add($r) } } return $result } } } |