openfiles.ps1
<#PSScriptInfo .VERSION 1.0 .GUID 579b9002-4c7a-4f16-b5ab-91f434aa9854 .AUTHOR Christoph Weste .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .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 Get-OpenFiles -ComputerName fileserver1 .EXAMPLE Get-OpenFiles -computername fs2 -Filter Open_File -query \share\ .EXAMPLE get-clippboard|Get-OpenFiles -Filter Accessed_By -query backupadmin .EXAMPLE 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 query This is your 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')] 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')] [AllowEmptyString()] [String]$Filter, [Parameter(Position = 2)] [AllowEmptyString()] [String]$query, [Parameter(Position = 3)] [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' { $dvFileAccess.RowFilter = 'Accessed_By'+(" LIKE '%{0}%'" -f $query) } 'Open_File' { $dvFileAccess.RowFilter = ("Open_File LIKE '%{0}%'" -f $query) } default { If ($Terminate -ne $True) { return $dtFileAccess } } } # Result if ( $Terminate -eq $True ) { #-and $dvFileAccess.GetEnumerator() -gt 0){ $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 } return $dvFileAccess } } |