sintaxis - Secuencia de comandos de PowerShell para comprobar una aplicación que está bloqueando un archivo?
powershell conexion remota (7)
Usando en PowerShell, ¿cómo puedo verificar si una aplicación está bloqueando un archivo?
Me gusta comprobar qué proceso / aplicación está usando el archivo, para poder cerrarlo.
Debería poder usar el comando openfiles desde la línea de comando regular o desde PowerShell.
La herramienta integrada de archivos abiertos se puede usar para compartir archivos o para archivos locales. Para los archivos locales, debe encender la herramienta y reiniciar la máquina (nuevamente, solo para usarla por primera vez). Creo que el comando para activar esta función es:
openfiles /local on
Por ejemplo (funciona en Windows Vista x64):
openfiles /query | find "chrome.exe"
Eso devuelve con éxito los identificadores de archivos asociados con Chrome. También puede pasar un nombre de archivo para ver el proceso que actualmente está accediendo a ese archivo.
Esto podría ayudarlo: use PowerShell para averiguar qué proceso bloquea un archivo . Analiza la propiedad System.Diagnostics.ProcessModuleCollection Modules de cada proceso y busca la ruta del archivo bloqueado:
$lockedFile="C:/Windows/System32/wshtcpip.dll"
Get-Process | foreach{$processVar = $_;$_.Modules | foreach{if($_.FileName -eq $lockedFile){$processVar.Name + " PID:" + $processVar.id}}}
He visto una buena solución en la detección de archivos bloqueados que usa únicamente clases de PowerShell y .NET framework:
function TestFileLock {
## Attempts to open a file and trap the resulting error if the file is already open/locked
param ([string]$filePath )
$filelocked = $false
$fileInfo = New-Object System.IO.FileInfo $filePath
trap {
Set-Variable -name filelocked -value $true -scope 1
continue
}
$fileStream = $fileInfo.Open( [System.IO.FileMode]::OpenOrCreate,[System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None )
if ($fileStream) {
$fileStream.Close()
}
$obj = New-Object Object
$obj | Add-Member Noteproperty FilePath -value $filePath
$obj | Add-Member Noteproperty IsLocked -value $filelocked
$obj
}
Me gusta lo que tiene el símbolo del sistema (CMD) y también se puede usar en PowerShell:
tasklist /m <dllName>
Solo tenga en cuenta que no puede ingresar la ruta completa del archivo DLL. Solo el nombre es lo suficientemente bueno.
Puede encontrar una solución usando la utilidad Sysinternal ''s Handle .
Tuve que modificar el código (ligeramente) para trabajar con PowerShell 2.0:
#/* http://jdhitsolutions.com/blog/powershell/3744/friday-fun-find-file-locking-process-with-powershell/ */
Function Get-LockingProcess {
[cmdletbinding()]
Param(
[Parameter(Position=0, Mandatory=$True,
HelpMessage="What is the path or filename? You can enter a partial name without wildcards")]
[Alias("name")]
[ValidateNotNullorEmpty()]
[string]$Path
)
# Define the path to Handle.exe
# //$Handle = "G:/Sysinternals/handle.exe"
$Handle = "C:/tmp/handle.exe"
# //[regex]$matchPattern = "(?<Name>/w+/./w+)/s+pid:/s+(?<PID>/b(/d+)/b)/s+type:/s+(?<Type>/w+)/s+/w+:/s+(?<Path>.*)"
# //[regex]$matchPattern = "(?<Name>/w+/./w+)/s+pid:/s+(?<PID>/d+)/s+type:/s+(?<Type>/w+)/s+/w+:/s+(?<Path>.*)"
[regex]$matchPattern = "(?<Name>/w+/./w+)/s+pid:/s+(?<PID>/d+)/s+type:/s+(?<Type>/w+)/s+(?<User>/.+)/s+/w+:/s+(?<Path>.*)"
$data = &$handle -u $path
$MyMatches = $matchPattern.Matches( $data )
# //if ($MyMatches.value) {
if ($MyMatches.count) {
$MyMatches | foreach {
[pscustomobject]@{
FullName = $_.groups["Name"].value
Name = $_.groups["Name"].value.split(".")[0]
ID = $_.groups["PID"].value
Type = $_.groups["Type"].value
User = $_.groups["User"].value.trim()
Path = $_.groups["Path"].value
toString = "pid: $($_.groups["PID"].value), user: $($_.groups["User"].value), image: $($_.groups["Name"].value)"
} #hashtable
} #foreach
} #if data
else {
Write-Warning "No matching handles found"
}
} #end function
Ejemplo:
PS C:/tmp> . ./Get-LockingProcess.ps1
PS C:/tmp> Get-LockingProcess C:/tmp/foo.txt
Name Value
---- -----
ID 2140
FullName WINWORD.EXE
toString pid: 2140, user: J17/Administrator, image: WINWORD.EXE
Path C:/tmp/foo.txt
Type File
User J17/Administrator
Name WINWORD
PS C:/tmp>
Puede hacer esto con la herramienta SysInternals handle.exe . Pruebe algo como esto:
PS> $handleOut = handle
PS> foreach ($line in $handleOut) {
if ($line -match ''/S+/spid:'') {
$exe = $line
}
elseif ($line -match ''C://Windows//Fonts//segoeui/.ttf'') {
"$exe - $line"
}
}
MSASCui.exe pid: 5608 ACME/hillr - 568: File (---) C:/Windows/Fonts/segoeui.ttf
...
Si modifica la función anterior ligeramente como a continuación, devolverá True o False (deberá ejecutar con todos los derechos de administrador), por ejemplo, Uso:
PS> TestFileLock "c: / pagefile.sys"
function TestFileLock {
## Attempts to open a file and trap the resulting error if the file is already open/locked
param ([string]$filePath )
$filelocked = $false
$fileInfo = New-Object System.IO.FileInfo $filePath
trap {
Set-Variable -name Filelocked -value $true -scope 1
continue
}
$fileStream = $fileInfo.Open( [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None )
if ($fileStream) {
$fileStream.Close()
}
$filelocked
}