【问题标题】:Iterating over PowerShell $input遍历 PowerShell $input
【发布时间】:2012-10-02 13:03:27
【问题描述】:

在将文件项传递给函数然后在 foreach 循环中使用 $input 时,我遇到了一些奇怪的行为(如在非确定性中)。

我这样调用我的函数...

get-childitem Stuff | Create-Zip C:\Stuff.zip

其中“Stuff”包含一堆包含目录和子目录的文件夹。问题是,在重复运行时,一些顶级目录不会被复制,无论它们是否为空。

这个函数几乎是http://blogs.msdn.com/b/daiken/archive/2007/02/12/compress-files-with-windows-powershell-then-package-a-windows-vista-sidebar-gadget.aspx那个函数的直接拷贝

function Create-Zip
{
    param([string]$zipfile)
    set-content $zipfile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
    (dir $zipfile).IsReadOnly = $false  

    $shellApplication = new-object -comObject Shell.Application
    $zipPackage = $shellApplication.NameSpace($zipfile)

    foreach($item in $input)
    { 
        $zipPackage.CopyHere($item.FullName)
        Start-sleep -milliseconds 500
    }
}

问题似乎出在 Start-Sleep 行 - 如果我完全省略它,则 zip 文件为空...如果我将其增加到 10 秒,则 zip 文件通常已满。为什么会这样,有没有更好的方法来写这个而不依赖于睡眠值?

【问题讨论】:

    标签: powershell foreach comobject


    【解决方案1】:

    $input 应该在 process {} 脚本块的上下文中进行评估,例如:

    function Create-Zip
    {
        param([string]$zipfile)
         set-content $zipfile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
         (dir $zipfile).IsReadOnly = $false 
    
        $shellApplication = new-object -comObject Shell.Application
        $zipPackage = $shellApplication.NameSpace($zipfile)
    
        process {
            foreach($item in $input)
            { 
                $zipPackage.CopyHere($item.FullName)
                Start-sleep -milliseconds 500
            }
        }
    }
    

    但是,如果您使用的是 PowerShell V2,这是传递与文件(字符串路径、FileInfo 等)相关的管道输入的更好方法:

    function Verb-Noun
    {
        [CmdletBinding(DefaultParameterSetName="Path")]
        param(
            [Parameter(Mandatory=$true, Position=0, ParameterSetName="Path", 
                       ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true,
                       HelpMessage="Path to ...")]
            [ValidateNotNullOrEmpty()]
            [string[]]
            $Path,
    
            [Alias("PSPath")]
            [Parameter(Mandatory=$true, Position=0, ParameterSetName="LiteralPath", 
                       ValueFromPipelineByPropertyName=$true,
                       HelpMessage="Path to ...")]
            [ValidateNotNullOrEmpty()]
            [string[]]
            $LiteralPath
        )
    
        Begin { Set-StrictMode -Version latest }
    
        Process {
            if ($psCmdlet.ParameterSetName -eq "Path")
            {
                # In the -Path (non-literal) case we may need to resolve a wildcarded path
                $resolvedPaths = @($Path | Resolve-Path | Convert-Path)
            }
            else 
            {
                # Must be -LiteralPath
                $resolvedPaths = @($LiteralPath | Convert-Path)
            }
    
            foreach ($rpath in $resolvedPaths) 
            {
                Write-Verbose "Processing $rpath"
                # ... Do something with the raw, resolved $rpath here ...
            }  
        }
    }
    

    【讨论】:

      【解决方案2】:

      我注意到 ParseName 在处理项目时返回 null,因此您可以使用以下代码:

      function Create-Zip
      {
          param([string]$zipfile)
               set-content $zipfile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
               (dir $zipfile).IsReadOnly = $false 
      
          $shellApplication = new-object -comObject Shell.Application
          $zipPackage = $shellApplication.NameSpace($zipfile)
      
          foreach($item in $input)
          { 
                   $zipPackage.CopyHere($item.FullName)
                   do {
                      $i = $zipPackage.ParseName($item.Name)
                      Start-Sleep -milliseconds 10
                  } while ($i -eq $null)
          }
      }
      

      它在这里工作没有问题,即使没有 Start-Sleep,它只是为了不烧坏 CPU。

      【讨论】:

        猜你喜欢
        • 2021-01-11
        • 2016-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-17
        • 2013-10-24
        • 2021-11-22
        • 2013-09-01
        相关资源
        最近更新 更多