2012-10-02 84 views
0

將文件項傳遞給函數並在foreach循環中使用$ input時,我遇到了一些奇怪的行爲(如非確定性行爲)。

我打電話給我的功能是這樣的...

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

其中「東西」,包含了一些包含目錄和子目錄的文件夾。問題是,在重複運行時,不管它們是否爲空,某些頂級目錄都不會被複制。

的功能是一個在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 
    } 
} 

的問題幾乎是直接複製似乎是開始睡眠線 - 如果我省略此完全,zip文件是空的......如果我把它增加到10秒,zip文件通常是滿的。爲什麼會這樣呢,還有更好的方法來寫這個,而不依賴於睡眠值嗎?

回答

0

$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 ... 
     } 
    } 
} 
0

我注意到,當PARSENAME項目beeing處理,使您可以使用此代碼返回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) 
    } 
} 

它在這裏沒有問題,即使沒有啓動睡眠,這是沒有燒壞CPU。