提高Get-FileMetaData的速度

时间:2017-03-21 06:44:49

标签: powershell

我目前正在使用从scriptingguys.com获取的以下脚本(所有这些都归功于他们,我刚刚添加了底部的2行。)这需要一个目录并从元数据中提取文件路径和注释字段。文件。目前,该脚本需要1.5分钟才能完全运行。无论如何要加快速度或使用不同的方法来获取这些数据?

我在我编写的某些软件的开头使用这个脚本,并且1.5+分钟对于脚本来说太长了。有什么想法/评论吗?

Function Get-FileMetaData
{
 Param([string[]]$folder)
 foreach($sFolder in $folder)
  {
   $a = 0
   $objShell = New-Object -ComObject Shell.Application
   $objFolder = $objShell.namespace($sFolder)

   foreach ($File in $objFolder.items())
    { 
     $FileMetaData = New-Object PSOBJECT
      for ($a ; $a  -le 266; $a++)
       { 
         if($objFolder.getDetailsOf($File, $a))
           {
             $hash += @{$($objFolder.getDetailsOf($objFolder.items, $a))  =
                   $($objFolder.getDetailsOf($File, $a)) }
            $FileMetaData | Add-Member $hash
            $hash.clear() 
           } #end if
       } #end for 
     $a=0
     $FileMetaData
    } #end foreach $file
  } #end foreach $sfolder
} #end Get-FileMetaData

$fileMetaData = Get-FileMetaData -folder "C:\Pics" | select 'Name', 'Path', 'Comments' | Sort-Object 'Name'
$fileMetaData | select 'Name', 'Path', 'Comments' | Export-CSV "C:\SCRIPTS\TestDirectory.txt" -encoding Utf8 -NoTypeInformation

由wOxxOm解决,感谢您的帮助!运行以下,现在正在工作。

Function Get-FileMetaData(
    [string[]]$folders,
    [string[]]$properties
) {
    $shellApp = New-Object -ComObject Shell.Application
    $supportsOrdered = $PSVersionTable.PSVersion.Major -ge 3
    $hash = if ($supportsOrdered) { [ordered]@{} } else { @{} }
    # walk the folders and get the properties by index found above
    $folders | ForEach {
        $shellFolder = $shellApp.namespace($_)
        # get all headers and find their indexes
        $allProps = @{}
        foreach ($index in 0..266) {
            $allProps[$shellFolder.getDetailsOf($shellFolder.items, $index)] = $index
        }
        $shellFolder.items() | ForEach {
            $file = $_
            $hash.Clear()
            foreach ($prop in $properties) { 
                if (($index = $allProps[$prop]) -ne $null) {
                    if ($value = $shellFolder.getDetailsOf($file, $index)) {
                        $hash[$prop] = $value
                    }
                }
            }
            if ($supportsOrdered) {
                [PSCustomObject]$hash
            } else {
                Select $properties -inputObject (
                    New-Object PSObject -Property $hash
                )
            }
        }
    }
}
Get-FileMetaData  -folders 'C:\PICS' -properties Name, Path, Comments | Sort-Object Name |
    select Name, Path, Comments | Export-Csv 'C:\Scripts\test.txt' -encoding UTF8 -NoTypeInformation

1 个答案:

答案 0 :(得分:1)

  1. getDetailsOf很慢,当你只需要3个属性时,你的代码会为每个文件不必要地调用它267次。
  2. 在功能开始时只收集一次属性名称,不要在每个文件上执行此操作
  3. Add-Member很慢。不要在每个房产上调用它。在哈希表中收集所有找到的属性并将其传递给Add-Member,或者,因为您创建一个空对象,直接到New-Object。要强制执行属性顺序,请在PowerShell 2中使用Select-Object。注意,PowerShell 3.0和更新的支持[ordered][PSCustomObject]类型转换(请参阅下面的代码)。
  4. 使用管道传输代替foreach语句,以便立即显示结果
  5. 文件已按名称排序,至少在Windows的NTFS文件系统中排序,因此无需排序。
  6. Function Get-FileMetaData(
        [string[]]$folders,
        [string[]]$properties
    ) {
        $shellApp = New-Object -ComObject Shell.Application
        # get all headers and find their indexes
        $shellFolder = $shellApp.namespace($folders[0])
        $allProps = @{}
        foreach ($index in 0..266) {
            $allProps[$shellFolder.getDetailsOf($shellFolder.items, $index)] = $index
        }
        $supportsOrdered = $PSVersionTable.PSVersion.Major -ge 3
        $hash = if ($supportsOrdered) { [ordered]@{} } else { @{} }
        # walk the folders and get the properties by index found above
        $folders | ForEach {
            $shellFolder = $shellApp.namespace($_)
            $shellFolder.items() | ForEach {
                $file = $_
                $hash.Clear()
                foreach ($prop in $properties) { 
                    if (($index = $allProps[$prop]) -ne $null) {
                        $hash[$prop] = $shellFolder.getDetailsOf($file, $index)
                    }
                }
                if ($supportsOrdered) {
                    [PSCustomObject]$hash
                } else {
                    Select $properties -inputObject (
                        New-Object PSObject -Property $hash
                    )
                }
            }
        }
    }
    

    用法示例1:

    Get-FileMetaData -folders 'r:\folder1', 'r:\folder2' -properties Name, Path, Comments
    

    用法示例2:

    Get-FileMetaData -folders 'r:\folder1', 'r:\folder2' -properties Name, Path, Comments |
        Export-Csv r:\results.csv -encoding UTF8 -NoTypeInformation
    

    用法示例3获取所有属性,这很慢:

    Get-FileMetaData -folders 'r:\folder1', 'r:\folder2'