Comment gérer les descripteurs de fichiers ouverts avec PowerShell

Contenu

Les personnes en ligne de commande

L'une des erreurs les plus frustrantes qu'un utilisateur final ou un administrateur informatique puisse gérer est le verrouillage des fichiers dans Windows.. Lorsque vous supprimez un dossier, vous déplacez un fichier ou modifiez un paramètre et vous rencontrez un message d'erreur de fichier verrouillé, mieux s'en occuper rapidement et efficacement.

Microsoft a introduit PowerShell comme shell de remplacement, mais il a beaucoup plus de fonctionnalités que cela et c'est un langage complexe et capable. Voyons dans cet article comment utiliser PowerShell pour gérer les fichiers verrouillés.

Le problème du fichier verrouillé

Comment verrouillez-vous exactement un fichier? Tout au long d'une utilisation normale, une procédure crée de nombreux identifiants de ressources en un seul fichier. Ce faisant, les processus verrouillent souvent le fichier pour empêcher les modifications de configuration indésirables ou toute autre corruption. Le problème est souvent qu'il est difficile de déterminer quelle procédure a verrouillé le fichier et, plus tard, comment effacer ce verrou de fichier.

Malheureusement, il n'y a pas d'applet de commande intégrée pour tester un fichier et savoir s'il est verrouillé ou par quelle procédure. Pour cela, vous devez créer vos propres fonctions ou emballer d'autres outils utiles pour vous aider à en savoir plus sur ces fichiers.

Test des fichiers verrouillés

À l'intérieur des fenêtres, vous pouvez tester pour voir si un fichier individuel est verrouillé. Avec le bloc de code suivant, vous pouvez tester pour voir si un certain fichier est verrouillé. Les $Item La variable doit être définie sur un chemin de fichier complet. Lors du test pour voir si le fichier peut être ouvert en écriture, à quoi ça ressemble avec lui [System.IO.File]::Open($Item,'Open','Write') commander, vous pouvez savoir si le fichier est verrouillé.

If ([System.IO.File]::Exists($Item)) {
  Try {
      $FileStream = [System.IO.File]::Open($Item,'Open','Write')

      $FileStream.Close()
      $FileStream.Dispose()

      $IsLocked = $False
  } Catch [System.UnauthorizedAccessException] {
      $IsLocked = 'AccessDenied'
  } Catch {
      $IsLocked = $True
  }
}

Get-SMBOpenFile

J'ai dit que Windows n'a pas de fonction intégrée, mais il y a un cas où une fonction existe. Si vous avez un partage distant ou même administratif (Quoi c$), alors vous pouvez utiliser le Get-SMBOpenFile applet de commande pour signaler ces fichiers ouverts.

PS C:> Get-SMBOpenFile

FileId       SessionId    Path  ShareRelativePath
------       ---------    ----  -----------------
154618822665 154618822657 C:

PS C:> 

L'inconvénient est que cela ne fonctionne que pour les fichiers accessibles à distance. Aucun fichier verrouillé en cours d'utilisation sur votre système local ne sera signalé, donc dans la plupart des cas ce n'est pas une solution viable. Pour fermer, vous pouvez rediriger les fichiers ouverts renvoyés vers le Close-SMBOpenFile commander.

Get-SMBOpenFile | Close-SMBOpenFile

Utilitaire OpenFiles

Windows a un utilitaire intégré appelé openfiles qui peut aider à lister les fichiers en cours d'utilisation et à les déconnecter. À première vue, semble parfait pour vos besoins! Vous pouvez même l'encapsuler dans une fonction PowerShell pour faciliter la vérification et la déconnexion des fichiers..

Ouvrez une invite d'administration PowerShell et exécutez la commande openfiles /query. Immédiatement, vous devriez recevoir un message d’erreur indiquant que l’indicateur global “gérer la liste des objets” doit être activé.

PS C:/> openfiles /query

INFO: The system global flag 'maintain objects list' needs
      to be enabled to see local opened files.
      See Openfiles /? for more information.


Files opened remotely via local share points:
---------------------------------------------

INFO: No shared open files found.

Cette liste d'objets est ce qui maintient vraiment la liste des identifiants qui sont en cours d'utilisation et permet openfiles consulter ces informations. Pour activer ce, entrer à l'intérieur openfiles /local on puis redémarrez votre ordinateur. L'inconvénient de l'activation de cette fonctionnalité est qu'il y a un léger impact sur les performances, que selon votre système, cet outil peut ne pas valoir la peine d'être utilisé. Cela dit, voyons comment nous pouvons faire en sorte que cela fonctionne dans PowerShell.

PS C:> openfiles /Query /fo csv /nh

Files opened remotely via local share points:
---------------------------------------------
"ID","Accessed By","Type","Open File (Pathexecutable)"
"608","user","Windows","C:"

PS C:> openfiles /Query /fo csv | Select-Object -Skip 4 | ConvertFrom-CSV

ID  Accessed By  Type    Open File (Pathexecutable)
--  -----------  ----    ---------------------------
608 user         Windows C:

PS C:> openfiles /disconnect /id 608

SUCCESS: The connection to the open file "C:" has been terminated.

Avec les exemples ci-dessus, vous pouvez voir comment importer la sortie CSV à partir de openfiles et PowerShell. Avec ces informations, il peut disconnect un fichier à débloquer. En raison de l'impact sur les performances que vous pouvez subir lors de l'activation du maintain objects list capacité, peut-être pas la peine pour vos besoins. C'est pourquoi, d'autres solutions peuvent être nécessaires.

L'application de la poignée

Sysinternals est connu pour les nombreux outils informatiques utiles et presque essentiels qu'il fabrique. Ça fait longtemps, Microsoft a acquis Sysinternals et vous pouvez télécharger et utiliser vous-même ces outils bien pris en charge. Idéalement, il y a une application qui s'appelle handles qui fournit exactement ce que vous recherchez.

Premier, tu devrais décharger application, décompressez les fichiers et placez les exécutables dans un emplacement qui a inclus votre variable d'environnement Path. Ce faisant, vous pouvez facilement référencer l'application là où vous en avez besoin. Avec une simple requête pour les fichiers ouverts, vous pouvez voir que vous obtenez beaucoup de résultats (tronqué pour une lecture facile).

PS C:/> handle64 -NoBanner
...
------------------------------------------------------------------------------
RuntimeBroker.exe pid: 9860 User
   48: File          C:WindowsSystem32
  188: Section       BaseNamedObjects__ComCatalogCache__
  1EC: Section       BaseNamedObjects__ComCatalogCache__
------------------------------------------------------------------------------
chrome.exe pid: 4628 User
   78: File          C:Program Files (x86)GoogleChromeApplication78.0.3904.108
  1C4: Section       Sessions1BaseNamedObjectswindows_shell_global_counters
...

Vous semblez obtenir ce que vous voulez, au moins un moyen de savoir quels fichiers sont utilisés, et vous pouvez les tester en utilisant votre code de fichier verrouillé d'avant. Mais, Comment rendre cela plus facile à utiliser? Le code suivant lit chaque procédure et récupère uniquement les fichiers verrouillés. L'inconvénient est que cela prend un certain temps à s'exécuter car il existe de nombreux processus.

$Processes = Get-Process

$results = $Processes | Foreach-Object {
    $handles = (handle64 -p $_.ID -NoBanner) | Where-Object { $_ -Match " File " } | Foreach-Object {
            [PSCustomObject]@{
        "Hex"  = ((($_ -Split " ").Where({ $_ -NE "" })[0]).Split(":")[0]).Trim()
        "File" = (($_ -Split " ")[-1]).Trim()
        }
    }

    If ( $handles ) {
        [PSCustomObject]@{
            "Name"    = $_.Name
            "PID"     = $_.ID
            "Handles" = $handles
        }
    }
}

Malgré cela, en dernier recours, ce que vous obtenez est une collection de fichiers exploitables, répertorié par procédure, que vous savez sont en cours d'utilisation et peuvent être filtrés davantage. Si vous trouvez que vous devez fermer l'un d'entre eux, vous pouvez faire ce qui suit (en tant qu'administrateur):

PS C:> $results |
>>  Where-Object Name -EQ 'Notepad' |
>>  Where-Object { $_.Handles.File -Match "test.txt" }

Name                      PID Handles
----                      --- -------
Notepad                   12028 {@{Hex=44; File=C:test.txt}


PS C:> handle64 -p 12028 -c 44 -y -nobanner

44: File  (R-D)   C:test.txt

Handle closed.

Vous pouvez encore envelopper tout cela dans une seule fonction pour faciliter encore plus l'analyse et la recherche selon les besoins.. Il existe de nombreuses alternatives, notamment en combinant plusieurs méthodes dans une solution adaptée à votre environnement.

conclusion

Traiter des fichiers verrouillés peut être difficile, surtout quand tu arrêtes ce que tu dois faire rapidement. Il existe plusieurs alternatives pour trouver et déverrouiller ces fichiers, mais cela demande un peu de travail car Windows n'a pas de méthode intégrée vraiment complète pour gérer ces fichiers verrouillés. Les solutions décrites doivent garder le problème bref et vous permettre de passer à des tâches beaucoup plus importantes.

Abonnez-vous à notre newsletter

Nous ne vous enverrons pas de courrier SPAM. Nous le détestons autant que vous.