web-dev-qa-db-fra.com

Get-ChildItem -force les rapports "Accès refusé" dans le dossier Mes documents et d'autres points de jonction.

J'ai un script que j'ai écrit qui remplace les fichiers. Je lui passe les paramètres pour le nom du fichier et l'emplacement de la base de recherche. Les lignes de travail sont:

$SubLocations = Get-ChildItem -Path $Startlocation -Recurse -include $Filename -Force  | 
                Where { $_.FullName.ToUpper().contains($Filter.ToUpper())}

J'ai défini $ Startlocation sur "C:\Users", cependant, l'accès est refusé lorsque j'essaie de recurse à travers les dossiers d'autres utilisateurs. Je suis administrateur complet sur la machine et j'ai déjà essayé d'exécuter Powershell en tant qu'administrateur. Je peux accéder à tous les fichiers via l'Explorateur Windows sans problème. Une idée?

Get-ChildItem : Access to the path 'C:\Users\jepa227\Documents\My Music' is denied.
At C:\Users\krla226\Google Drive\Documents\PowerShell\Replace-File.ps1:35 char:46
+ $SubLocations = Get-ChildItem <<<<  -Path $Startlocation -Recurse -    include $Filename -Force | 
    + CategoryInfo          : PermissionDenied: (C:\Users\jepa227\Documents\My     Music:String) [Get-ChildItem], Una 
   uthorizedAccessException
+ FullyQualifiedErrorId :  DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

METTRE &AGRAVE; JOUR

Alors que je ne pouvais pas le faire fonctionner via GCI, j'ai pu utiliser WMI pour résoudre mon problème. Pour ceux intéressés:

$SubLocations = Get-WmiObject -Class cim_datafile -Filter "fileName = '$filename' AND Extension = '$extension'" | 
                            Where { $_.Name.ToUpper().contains($Filter.ToUpper()) }
11
Kevin_

J'ai été en mesure de reproduire cela sur un ordinateur Windows 7 à l'aide de la commande suivante, connectée en tant qu'utilisateur admin nommé "admin", exécutant powershell avec des privilèges élevés et le contrôle de compte d'utilisateur désactivé:

get-childitem "c:\users\Admin\my documents"

et

cd "c:\users\admin\my documents"
get-childitem

D'après l'article ici , on dirait que Mes documents, Ma musique, etc., sont définis comme des points de jonction pour une compatibilité ascendante avec les logiciels antérieurs à Vista. Powershell ne fait pas bien nativement avec les points de jonction. Il semble y avoir quelques options ici:

1) Supprimez -force de la commande Get-ChildItem. C'est probablement votre meilleur pari.

get-childitem c:\users -recurse

fonctionne sans erreur et ignore les points de jonction et les répertoires système comme AppData.

Note de l'éditeur: Omettre -Force résout le problème immédiat, mais ignore invariablement tous les éléments cachés , et pas uniquement les points de jonction masqués à l'origine des erreurs d'accès refusé.

2) Si vous devez absolument utiliser le -Force pour une raison quelconque, vous pouvez ré-initialiser par programme chaque sous-répertoire en ignorant les points de jonction. Cet article décrit le mécanisme d'identification des points de jonction. Un squelette de ceci dans un fichier script .ps1 pourrait ressembler à ceci:

Param( [Parameter(Mandatory=$true)][string]$startLocation )

$errorActionPreference = "Stop"

function ProcessDirectory( $dir )
{
  Write-Host ("Working on " + $dir.FullName)

  # Work on the files in this folder here
  $filesToProcess = ( gci | where { ($_.PsIsContainer -eq 0) } ) # and file matches the requested pattern
  # process files

  $subdirs = gci $dir.FullName -force | where {($_.Attributes -band [IO.FileAttributes]::ReparsePoint) -eq 0 -and ($_.PsIsContainer -eq 1) -and (![string]::IsNullOrEmpty($_.FullName))}

  foreach( $subdir in $subdirs )
  {
      # Write-Host( $subdir.Name + ", " + $subdir.FullName )
     if ( $subdir -ne $null )
     {
       ProcessDirectory -dir $subdir
     }
  }
}

$dirs = get-childitem $startLocation -force
$dirs | foreach { ProcessDirectory -dir $_ }
4
mcating

La réponse utile de mcating explique bien le problème.

La solution rapide qu'il suggère est d'omettre -Force, ce qui fonctionne, car PowerShell ignore éléments masqués, sauf si -Force est utilisé, et ces points de jonction définis par le système ont l'attribut Hidden (à côté des attributs ReparsePoint et System).

Si vous avez besoin de -Force pour traiter les éléments masqués en général et que vous souhaitez uniquement ignorer ces points de jonction définis par le système , vous pouvez utiliser le paramètre Get-ChildItem de -Attributes comme suit:

Get-ChildItem -Force -Recurse -Attributes !Hidden, !System, !ReparsePoint

La valeur -Attributesexclut tous les éléments pour lesquels tous des attributs suivants sont définis: Hidden, System, ReparsePoint, ce qui est vrai de tous les points de jonction définis par le système.
Bien qu'il soit techniquement possible de créer vos propres points de jonction (ou liens symboliques) avec ces attributs, il est peu probable que cela se produise dans la pratique.

1
mklement0