web-dev-qa-db-ja.com

Get-ChildItem -forceは、マイドキュメントフォルダーおよびその他のジャンクションポイントで「アクセス拒否」を報告します

ファイルを置き換えるスクリプトを作成しました。ファイルの名前と検索するベースの場所のparamsを渡します。ワーカーラインは次のとおりです。

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

$ Startlocationを "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()) }
11
Kevin_

これをWindows 7マシンで再現するには、「admin」という管理ユーザーとしてログインし、管理者特権でpowershellを実行し、UACを無効にします。

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

そして

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

記事 here に基づいて、My Documents、My Musicなどは、Vista以前のソフトウェアとの後方互換性のための接合点として定義されています。 Powershellは、ネイティブのジャンクションポイントではうまく機能しません。ここにはいくつかのオプションがあるようです:

1)Get-ChildItemコマンドから-forceを削除します。これはおそらくあなたの最善の策です。

get-childitem c:\users -recurse

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

編集者注:-Forceを省略すると、差し迫った問題は解決されますが、アクセスを引き起こす非表示のジャンクションポイントだけでなく、すべての非表示アイテムが常にスキップされます-deniedエラー。

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

mcatingの役立つ答え は問題をよく説明しています。

彼が提案する迅速な修正は、-Forceを省略することです。これは、PowerShell ignores-Forceが使用され、これらのシステム定義のジャンクションポイントにHidden属性(ReparsePointおよびSystem属性とともに)。

一般的に非表示のアイテムを処理するために-Forceが必要であり、これらのシステム定義のジャンクションポイントのみを無視する場合は、 Get-ChildItem-Attributesパラメータは次のとおりです。

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

-Attributesexcludes次の属性セットのallを持つすべてのアイテム:HiddenSystemReparsePoint、これはすべてのシステム定義の接合点に当てはまります。
これらの属性を使用して独自のジャンクションポイント(またはシンボリックリンク)を作成することは技術的には可能ですが、これは実際には起こりそうにありません。

2
mklement0