我正在编写一个脚本来检查2 .zip文件的内容,比较每个.zip文件的名称(作为日期时间),然后删除最旧的2个文件。一切似乎工作得很好,直到最后我试图用一个简单的'Remove-Item'删除最旧的文件(我已经尝试了-Force选项没有改进)。我所做的每一次尝试都会导致此错误:
删除项目:无法删除项目C:\ Scripts \ Test2.zip:该过程 因为正在使用它,所以无法访问文件'C:\ Scripts \ Test2.zip' 通过另一个过程。在行:44 char:5 + Remove-Item $ newLocation -Force + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:WriteError:(C:\ Scripts \ Test2.zip:FileInfo)[Remove-Item],IOException + FullyQualifiedErrorId:RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
这是我提出的剧本(温柔,它可能不是地球上最顺畅的东西):
$scriptLocation = "C:\Scripts\"
$oldLocation = "C:\Scripts\Test1.zip"
$newLocation = "C:\Scripts\Test2.zip"
cd $scriptLocation
$fileOld = .\GetZipContents.ps1 -FileName $oldLocation | Where {$_.FileExtn -eq ".txt"}
$fileNew = .\GetZipContents.ps1 -FileName $newLocation | Where {$_.FileExtn -eq ".txt"}
function Convert-DateString ([String]$Date, [String[]]$Format)
{
$result = New-Object DateTime
$convertible = [DateTime]::TryParseExact(
$Date,
$Format,
[System.Globalization.CultureInfo]::InvariantCulture,
[System.Globalization.DateTimeStyles]::None,
[ref]$result)
if ($convertible) { $result }
}
$oldName = $fileOld.FileName
$oldDate = $oldName.Substring(0,$oldName.Length-4)
$newName = $fileNew.FileName
$newDate = $newName.Substring(0,$newName.Length-4)
$convOldDate = Convert-DateString -Date $oldDate -Format 'MMMM_dd_yyyy'
$convNewDate = Convert-DateString -Date $newDate -Format 'MMMM_dd_yyyy'
$compare = $convOldDate -ge $convNewDate
If($compare -eq $True)
#OLD
{
Remove-Item $oldLocation -Force
"OLD FILE IS OLD - REMOVING: ({0})" -f ($oldLocation)
}
Else
#NEW
{
Remove-Item $newLocation -Force
"NEW FILE IS NEW - REMOVING: ({0})" -f ($newLocation)
}
这是在$ fileOld和$ fileNew中调用的GetZipContents.ps1:
[cmdletbinding()]
param(
[Parameter(Mandatory=$true)]
[string[]]$FileName,
[String]$ExportCSVFileName
)
#Exit if the shell is using lower version of dotnet
$dotnetversion = [Environment]::Version
if(!($dotnetversion.Major -ge 4 -and $dotnetversion.Build -ge 30319)) {
write-error "You do not have Microsoft .Net Framework 4.5 installed. Script exiting..."
exit(1)
}
# Import dotnet libraries
[Void][Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
$ObjArray = @()
foreach($zipfile in $FileName) {
if(Test-Path $ZipFile) {
$RawFiles = [IO.Compression.ZipFile]::OpenRead($zipFile).Entries
foreach($RawFile in $RawFiles) {
$object = New-Object -TypeName PSObject
$Object | Add-Member -MemberType NoteProperty -Name FileName -Value $RawFile.Name
$Object | Add-Member -MemberType NoteProperty -Name FullPath -Value $RawFile.FullName
$Object | Add-Member -MemberType NoteProperty -Name CompressedLengthInKB -Value ($RawFile.CompressedLength/1KB).Tostring("00")
$Object | Add-Member -MemberType NoteProperty -Name UnCompressedLengthInKB -Value ($RawFile.Length/1KB).Tostring("00")
$Object | Add-Member -MemberType NoteProperty -Name FileExtn -Value ([System.IO.Path]::GetExtension($RawFile.FullName))
$Object | Add-Member -MemberType NoteProperty -Name ZipFileName -Value $zipfile
$ObjArray += $Object
if(!$ExportCSVFileName) {
$Object
}
}
} else {
Write-Warning "$ZipFileInput File path not found"
}
if ($ExportCSVFileName){
try {
$ObjArray | Export-CSV -Path $ExportCSVFileName -NotypeInformation
} catch {
Write-Error "Failed to export the output to CSV. Details : $_"
}
}
}
我从这里得到的是:http://techibee.com/powershell/reading-zip-file-contents-without-extraction-using-powershell/2152
我已经运行Handle.exe来查找打开这些文件的进程,并且它显示PowerShell ISE本身就是问题所在。
任何帮助将不胜感激。我试图搜索类似的问题,但只发现其他进程保持打开文件的问题,然后您可以使用Handle.exe终止。如果PowerShell ISE需要放手,我不知道如何做到这一点......
答案 0 :(得分:2)
当然,问题是你调用了[IO.Compression.ZipFile]::OpenRead()
但是你永远不会关闭文件。您应该在If
脚本块中执行的最后一件事是关闭您开始的OpenRead
。您正在使用的对象是System.IO.Compression.ZipArchive
,您可以在以下网址阅读:
https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110).aspx
您需要做的是释放您使用$ Rawfiles打开的文件实例的资源。为此,您可以调用Dispose()
方法。在我Else
陈述之前,我建议这样做。因此,将GetZipContents.ps1脚本更新为如下所示:
[cmdletbinding()]
param(
[Parameter(Mandatory=$true)]
[string[]]$FileName,
[String]$ExportCSVFileName
)
#Exit if the shell is using lower version of dotnet
$dotnetversion = [Environment]::Version
if(!($dotnetversion.Major -ge 4 -and $dotnetversion.Build -ge 30319)) {
write-error "You do not have Microsoft .Net Framework 4.5 installed. Script exiting..."
exit(1)
}
# Import dotnet libraries
[Void][Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
$ObjArray = @()
foreach($zipfile in $FileName) {
if(Test-Path $ZipFile) {
$RawFiles = [IO.Compression.ZipFile]::OpenRead($zipFile).Entries
foreach($RawFile in $RawFiles) {
$object = New-Object -TypeName PSObject
$Object | Add-Member -MemberType NoteProperty -Name FileName -Value $RawFile.Name
$Object | Add-Member -MemberType NoteProperty -Name FullPath -Value $RawFile.FullName
$Object | Add-Member -MemberType NoteProperty -Name CompressedLengthInKB -Value ($RawFile.CompressedLength/1KB).Tostring("00")
$Object | Add-Member -MemberType NoteProperty -Name UnCompressedLengthInKB -Value ($RawFile.Length/1KB).Tostring("00")
$Object | Add-Member -MemberType NoteProperty -Name FileExtn -Value ([System.IO.Path]::GetExtension($RawFile.FullName))
$Object | Add-Member -MemberType NoteProperty -Name ZipFileName -Value $zipfile
$ObjArray += $Object
if(!$ExportCSVFileName) {
$Object
}
}
$RawFiles.Dispose()
} else {
Write-Warning "$ZipFileInput File path not found"
}
if ($ExportCSVFileName){
try {
$ObjArray | Export-CSV -Path $ExportCSVFileName -NotypeInformation
} catch {
Write-Error "Failed to export the output to CSV. Details : $_"
}
}
}
答案 1 :(得分:2)
问题是GetZipContents.ps1在完成文件后没有关闭文件。 ZipFile::OpenRead
返回一个ZipArchive类(documented here),它实现IDisposable
。这表明ZipFile存档需要处理。
试试这个(注意对Dispose的调用:)
if(Test-Path $ZipFile) {
$ZipArchive = [IO.Compression.ZipFile]::OpenRead($zipFile)
$RawFiles = $ZipArchive.Entries
foreach($RawFile in $RawFiles) {
$Object = New-Object -TypeName PSObject
$Object | Add-Member -MemberType NoteProperty -Name FileName -Value $RawFile.Name
# etc. etc.
}
$RawFiles.Dispose()
} else {
Write-Warning "$ZipFileInput File path not found"
}
阅读IDisposable将会解释更多内容。