我将文件项传递给函数然后在foreach循环中使用$ input时会出现一些奇怪的行为(如非确定性)。
我正在调用我的函数......
get-childitem Stuff | Create-Zip C:\Stuff.zip
其中“Stuff”包含一堆包含目录和子目录的文件夹。问题是,在重复运行时,一些顶级目录不会被复制,无论它们是否为空。
的功能的直接副本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文件通常是满的。为什么会这样,并且有更好的方法来写这个而不依赖于睡眠值?
答案 0 :(得分: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 ...
}
}
}
答案 1 :(得分:0)
我注意到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。