1. ホーム
  2. powershell

[解決済み] Get-ChildItem -force で My Documents フォルダとその他の接続ポイントに "Access Denied" を報告する。

2022-02-16 12:43:20

質問

ファイルを置き換えるスクリプトを書きました。 ファイルの名前と、検索元のベースロケーションをパラメータとして渡しています。 ワーカーラインは次のとおりです。

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

このような場合、$Startlocationをquot;C: \Users" に設定しましたが、他のユーザーのフォルダを検索しようとすると、アクセス拒否されます。 私はこのマシンのフル管理者であり、管理者としてpowershellを実行することはすでに試しました。 私はWindowsエクスプローラ経由ですべてのファイルに問題なくアクセスすることができます。 何かいい方法はないでしょうか?

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

アップデイト

GCI経由で動作させることはできませんでしたが、WMIを使用して問題を解決することができました。 興味のある方のために。

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

解決方法は?

Windows7マシンで、"admin"という管理ユーザーでログインし、昇格権限でpowershellを実行し、UACを無効にして以下のコマンドで再現することができました。

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

そして

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

記事を元に作成 こちら マイドキュメント、マイミュージックなどは、Vista以前のソフトウェアとの後方互換性のために、ジャンクションポイントとして定義されているようです。Powershellはジャンクションポイントをうまく扱えません。いくつかのオプションがあるようです。

1) Get-ChildItem コマンドから -force を削除する。おそらくこれが最善の策です。

get-childitem c:\users -recurse

はエラーなく動作し、ジャンクションポイントやAppDataのようなシステムディレクトリはスキップされます。

編集後記 -Force は当面の問題を解決しますが、必ず すべて隠された の項目だけでなく、アクセス拒否のエラーの原因となる隠れた接続点にも注意が必要です。

2) どうしても必要な場合は -Force 何らかの理由で、プログラムによって各サブディレクトリを再帰的に検索し、分岐点をスキップすることができます。 この記事 には、ジャンクションポイントを特定するための仕組みが書かれています。.ps1スクリプトファイルでのスケルトンは、次のようになります。

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 $_ }