I've tried to write a commandlet for getting meta information from an epub file. I would like to use the commandlet like this:
Get-ChildItem '*.epub' | Get-EpubMetaInfo | %{ Rename-Item $_.File "$($_.Author) - $($_.Title).epub" }
So Get-EpubMetaInfo
should
- open the epub file (which is actually a simple a zip archive)
- read meta info from it
- close the opened stream
- passthru the meta infos
Here is the relevant part of the process block:
process
{
...
#
# 1. Open ZipArchive to get a DeflateStream reference
#
$Stream = $ZipEntry.Open()
try
{
#
# 2. Read meta-info
#
$Reader = [System.Xml.XmlReader]::create($Stream)
[System.Xml.XmlDocument] $opf = New-Object System.Xml.XmlDocument
$opf.Load($Reader)
$title = Get-MetaText $opf.package.metadata.title
...
}
catch [System.Exception]
{
Write-Error "Couldn't read meta-info $ZipEntry.Name from $EpubFile : $_.Message"
}
#
# 3. Close opened stream
#
finally
{
$Stream.Close()
$ZipEntry.Archive.Dispose()
# $ZipEntry doesn't have Close() or Dispose() method :(
}
$obj = New-Object –typename PSObject
#
# 4. passthru the infos
#
$obj | Add-Member –membertype NoteProperty –name File –value ($EpubFile) –passthru |
...
}
This works fine if I don't pipe it into the Rename-Item. With Rename-Item I get the following error:
Rename-Item : The process cannot access the file because it is being used by another process.
What should I do, to close the zip properly?
The whole code can be examined here https://github.com/mattia72/powershell
Update:
If I call $Reader.Close()
after $Stream.Close()
then the first rename is ok, the second fails again, and so on...
It may be an asynchronous reader issue?